From d6fb9e54fee2ba1c459aff2decd47777f9b4b1e4 Mon Sep 17 00:00:00 2001 From: zhezhitanye-code Date: Wed, 18 Mar 2026 10:45:58 +0800 Subject: [PATCH 1/8] chore: checkpoint ppt preview and planning snapshot --- ...07\346\241\243\346\225\264\347\220\206.md" | 2102 ++++++++++++ _tmp_docmee_aippt_vue | 1 + .../.gitignore | 30 + .../README.md | 69 + .../README_EN.md | 69 + .../env.d.ts | 1 + .../index.html | 13 + .../package-lock.json | 1380 ++++++++ .../package.json | 29 + .../public/favicon.png | Bin 0 -> 2725 bytes .../src/App.vue | 12 + .../src/assets/base.css | 86 + .../src/assets/logo.svg | 1 + .../src/assets/main.css | 5 + .../src/components/AiPpt.vue | 76 + .../src/components/GenerateOutline.vue | 211 ++ .../src/components/GeneratePpt.vue | 360 ++ .../src/components/OutlineEdit.vue | 194 ++ .../src/components/SelectTemplate.vue | 179 + .../src/main.ts | 6 + .../src/utils/animation.js | 2903 +++++++++++++++++ .../src/utils/chart.js | 834 +++++ .../src/utils/cover.js | 95 + .../src/utils/element.js | 692 ++++ .../src/utils/geometry.js | 500 +++ .../src/utils/ppt2canvas.js | 1328 ++++++++ .../src/utils/ppt2svg.js | 2265 +++++++++++++ .../src/utils/sse.js | 238 ++ .../tsconfig.app.json | 16 + .../tsconfig.json | 16 + .../tsconfig.node.json | 21 + .../vite.config.ts | 16 + docs/mockup-ppt-generation.html | 956 ++++++ .../plans/2026-03-18-ppt-generation-plan.md | 633 ++++ .../specs/2326-3-18-ppt-generation-spec.md | 626 ++++ 35 files changed, 15963 insertions(+) create mode 100644 "DOCMEE_API\346\226\207\346\241\243\346\225\264\347\220\206.md" create mode 160000 _tmp_docmee_aippt_vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/.gitignore create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README.md create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README_EN.md create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/env.d.ts create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/index.html create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package-lock.json create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package.json create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/public/favicon.png create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/App.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/base.css create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/logo.svg create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/main.css create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/AiPpt.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GenerateOutline.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json create mode 100644 aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts create mode 100644 docs/mockup-ppt-generation.html create mode 100644 docs/superpowers/plans/2026-03-18-ppt-generation-plan.md create mode 100644 docs/superpowers/specs/2326-3-18-ppt-generation-spec.md diff --git "a/DOCMEE_API\346\226\207\346\241\243\346\225\264\347\220\206.md" "b/DOCMEE_API\346\226\207\346\241\243\346\225\264\347\220\206.md" new file mode 100644 index 0000000..b6be90d --- /dev/null +++ "b/DOCMEE_API\346\226\207\346\241\243\346\225\264\347\220\206.md" @@ -0,0 +1,2102 @@ +# 文多多AiPPT开放平台API文档 + +## 目录 +- [接入流程](#接入流程) +- [接口鉴权](#接口鉴权) +- [API接口分类](#api接口分类) + - [AI PPT - V2](#ai-ppt---v2) + - [AI PPT - V1](#ai-ppt---v1) + - [模板管理](#模板管理) + - [PPT获取与操作](#ppt获取与操作) + - [积分和使用记录](#积分和使用记录) + - [其他接口](#其他接口) +- [错误码](#错误码) +- [特殊说明](#特殊说明) + +## 接入流程 + +文多多AiPPT API接入遵循标准的RESTful设计模式,主要流程如下: + +1. **获取API Key**:在[开放平台](https://open.docmee.cn/open)注册账号并获取API Key。 +2. **创建访问Token**:通过`createApiToken`接口创建具有时效性的访问Token。 +3. **调用业务接口**:在请求头中携带Token调用具体的业务接口。 +4. **处理响应**:根据接口返回的数据进行后续处理。 + +> **重要提示**:该接口请在服务端调用,同一个uid创建token时,之前通过该uid创建的token会在10秒内过期。 + +## 接口鉴权 + +### 创建接口Token + +用于生成调用鉴权Token,支持限制生成次数与数据隔离。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/user/createApiToken` | +| 请求方法 | POST | +| 请求头 | `Content-Type: application/json`, `Api-Key: xxx` | + +#### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| uid | string | 否 | 用户ID(自定义用户ID,非必填,建议不超过32位字符串),不同uid创建的token数据会相互隔离,主要用于数据隔离 | +| limit | number | 否 | 限制token最大生成PPT次数(数字,为空则不限制,为0时不允许生成PPT,大于0时限制生成PPT次数)。UI iframe接入时强烈建议传limit参数,避免token泄露造成损失! | +| timeOfHours | number | 否 | 过期时间,单位:小时,默认两小时过期,最大可设置为48小时 | + +#### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.token | string | token (调用api接口鉴权用,请求头传token) | +| data.expireTime | number | 过期时间(秒) | +| code | number | 状态码 | +| message | string | 提示信息 | + +#### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/user/createApiToken' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: xxx' \ +--data '{"uid": "xxx","limit": 10}' +``` + +### API接口鉴权 + +所有业务接口都需要进行鉴权。 + +| 属性 | 说明 | +|------|------| +| 请求头 | `token: {token}` 或直接使用 `Api-Key: {apiKey}` | + +#### 接口请求示例 +```bash +curl --location 'https://open.docmee.cn/api/ppt/xxx' \ +--header 'token: xxx' +``` + +> **注意**:封面图片资源访问,需要在url上拼接`?token=xxx`。 + +## API接口分类 + +### AI PPT - V2 + +官方推荐使用的最新版本API。 + +#### 创建任务 + +开启一个生成PPT的任务。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v2/createTask` | +| 请求方法 | POST | +| Content-Type | `multipart/form-data` | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| type | number | 是 | 类型:
1. 智能生成(主题、要求)
2. 上传文件生成
3. 上传思维导图生成
4. 通过word精准转ppt
5. 通过网页链接生成
6. 粘贴文本内容生成
7. Markdown大纲生成 | +| content | string | 否 | 内容:
- type=1:用户输入主题或要求(不超过1000字符)
- type=2,4:不传
- type=3:幕布等分享链接
- type=5:网页链接地址(http/https)
- type=6:粘贴文本内容(不超过20000字符)
- type=7:大纲内容(markdown) | +| file | File[] | 否 | 文件列表(文件数不超过5个,总大小不超过50M):
- type=1:上传参考文件(非必传,支持多个)
- type=2:上传文件(支持多个)
- type=3:上传思维导图(xmind/mm/md)(仅支持一个)
- type=4:上传word文件(仅支持一个)
- type=5,6,7:不传 | + +**支持格式**:doc/docx/pdf/ppt/pptx/txt/md/xls/xlsx/csv/html/epub/mobi/xmind/mm + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.id | string | 任务ID | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/v2/createTask' \ +--header 'Content-Type: multipart/form-data' \ +--form 'type=1' \ +--form 'content="AI未来的发展"' +``` + +#### 获取生成选项 + +获取调用生成大纲内容需要使用的相关选项。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v2/options` | +| 请求方法 | GET | + +> 该接口支持国际化,URL携带lang参数指定。 + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.lang | array | 语种选项 | +| data.scene | array | 场景选项 | +| data.audience | array | 受众选项 | +| code | number | 状态码 | +| message | string | 提示信息 | + +**语种(lang)选项**: +1. {name: "简体中文", value: "zh"} +2. {name: "繁體中文", value: "zh-Hant"} +3. {name: "English", value: "en"} +4. {name: "日本語", value: "ja"} +5. {name: "한국어", value: "ko"} +6. {name: "Français", value: "fr"} +7. {name: "Русский", value: "ru"} +8. {name: "العربية", value: "ar"} +9. {name: "Deutsch", value: "de"} +10. {name: "Español", value: "es"} +11. {name: "Italiano", value: "it"} +12. {name: "Português", value: "pt"} + +**场景(scene)选项**: +1. {name: "通用场景", value: "通用场景"} +2. {name: "教学课件", value: "教学课件"} +3. {name: "工作总结", value: "工作总结"} +4. {name: "工作计划", value: "工作计划"} +5. {name: "项目汇报", value: "项目汇报"} +6. {name: "解决方案", value: "解决方案"} +7. {name: "研究报告", value: "研究报告"} +8. {name: "会议材料", value: "会议材料"} +9. {name: "产品介绍", value: "产品介绍"} +10. {name: "公司介绍", value: "公司介绍"} +11. {name: "商业计划书", value: "商业计划书"} +12. {name: "科普宣传", value: "科普宣传"} +13. {name: "公众演讲", value: "公众演讲"} + +**受众(audience)选项**: +1. {name: "大众", value: "大众"} +2. {name: "学生", value: "学生"} +3. {name: "老师", value: "老师"} +4. {name: "上级领导", value: "上级领导"} +5. {name: "下属", value: "下属"} +6. {name: "面试官", value: "面试官"} +7. {name: "同事", value: "同事"} + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/ppt/v2/options?lang=zh' +``` + +#### 生成大纲内容 + +生成当前任务的大纲及内容。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v2/generateContent` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 任务ID | +| stream | boolean | 否 | 是否流式(默认true) | +| length | string | 否 | 篇幅长度:short/medium/long => 10-15页/20-30页/25-35页 | +| scene | string | 否 | 演示场景:通用场景、教学课件、工作总结、工作计划、项目汇报、解决方案、研究报告、会议材料、产品介绍、公司介绍、商业计划书、科普宣传、公众演讲等任意场景类型 | +| audience | string | 否 | 受众:大众、学生、老师、上级领导、下属、面试官、同事等任意受众类型 | +| lang | string | 否 | 语言: zh/zh-Hant/en/ja/ko/ar/de/fr/it/pt/es/ru | +| prompt | string | 否 | 用户要求(小于50字) | + +> **特别提醒**:参数`prompt`只会在创建的任务类型为1(智能生成), 2(上传文件生成), 5(通过网页链接生成), 6(粘贴文本内容生成)这些类型时生效,其他类型会忽略该字段。 + +##### 响应 +**流式响应(event-stream)**: +```json +{"text": "#", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{ + "text": "", + "status": 4, + "result": { + "level": 1, + "name": "主题", + "children": [ + { + "level": 2, + "name": "章节", + "children": [ + { + "level": 3, + "name": "页面标题", + "children": [ + { + "level": 4, + "name": "内容标题", + "children": [ + { + "level": 0, + "name": "内容" + } + ] + } + ] + } + ] + } + ] + } +} +``` + +**非流式响应(application/json)**: +```json +{ + "code": 0, + "data": { + "text": "# 主题\\n## 章节\\n### 页面标题\\n#### 内容标题\\n- 内容", + "result": { + "level": 1, + "name": "主题", + "children": [ + { + "level": 2, + "name": "章节", + "children": [ + { + "level": 3, + "name": "页面标题", + "children": [ + { + "level": 4, + "name": "内容标题", + "children": [ + { + "level": 0, + "name": "内容" + } + ] + } + ] + } + ] + } + ] + } + }, + "message": "ok" +} +``` + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/v2/generateContent' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx","stream":true,"length":"medium"}' +``` + +#### 修改大纲内容 + +根据用户指令修改大纲内容。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v2/updateContent` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 任务ID | +| stream | boolean | 否 | 是否流式(默认true) | +| markdown | string | 是 | 大纲内容markdown | +| question | string | 否 | 用户修改建议 | + +##### 响应 +event-stream或application/json,结构同生成大纲内容。 + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/v2/updateContent' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx","markdown":"# 主题\\n## 章节","question":"帮我优化一下结构"}' +``` + +#### 生成PPT + +根据markdown格式的PPT大纲与内容生成PPT作品。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v2/generatePptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 任务ID | +| templateId | string | 是 | 模板ID(调用模板接口获取) | +| markdown | string | 是 | 大纲内容markdown | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.pptInfo.id | string | ppt id | +| data.pptInfo.subject | string | 主题 | +| data.pptInfo.coverUrl | string | 封面 | +| data.pptInfo.templateId | string | 模板ID | +| data.pptInfo.pptxProperty | string | PPT数据结构(json gzip base64) | +| data.pptInfo.userId | string | 用户ID | +| data.pptInfo.userName | string | 用户名称 | +| data.pptInfo.companyId | number | 公司ID | +| data.pptInfo.updateTime | string/null | 更新时间 | +| data.pptInfo.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/v2/generatePptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx","templateId":"xxx","markdown":"# 主题\\n## 章节"}' +``` + +> 通过API生成PPT后,如果需要在前端进行编辑和渲染,推荐使用以下iframe方式编辑器: +> - github +> - gitee + +### AI PPT - V1 + +旧版本API,仍可使用但推荐使用V2版本。 + +#### 解析文件内容 + +将若干支持的参数选项转化成dataUrl以便后续接口使用。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/parseFileData` | +| 请求方法 | POST | +| Content-Type | `multipart/form-data` | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| file | File | 否 | 文件(限制50M以内,最大解析2万字) | +| content | string | 否 | 用户粘贴文本内容 | +| fileUrl | string | 否 | 文件公网链接 | +| website | string | 否 | 网址(http/https) | +| websearch | string | 否 | 网络搜索关键词 | + +**支持格式**:doc/docx/pdf/ppt/pptx/txt/md/xls/xlsx/csv/html/epub/mobi/xmind/mm + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.dataUrl | string | 文件数据url(有效期:当天) | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/parseFileData' \ +--header 'Content-Type: multipart/form-data' \ +--header 'token: {token}' \ +--form 'file=@test.doc;filename=test.doc' \ +--form 'content=文本内容' \ +--form 'fileUrl=https://xxx.pdf' \ +--form 'website=https://example.com' \ +--form 'websearch=上海元符号智能科技有限公司' +``` + +#### 生成大纲 + +V1版本的生成大纲接口。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/generateOutline` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| stream | boolean | 否 | 是否流式生成(默认流式) | +| length | string | 否 | 篇幅长度:short/medium/long, 默认medium, 分别对应: 10-15页/20-30页/25-35页 | +| lang | string | 否 | 语言: zh/zh-Hant/en/ja/ko/ar/de/fr/it/pt/es/ru | +| prompt | string | 否 | 用户要求(小于50字) | +| subject | string | 否 | 主题(与dataUrl可同时存在) | +| dataUrl | string | 否 | 文件数据url,通过解析文件内容接口返回(与subject可同时存在) | + +##### 响应 +```json +{"text": "", "status": 1} +{"text": "# ", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{ + "text": "", + "status": 4, + "result": { + "level": 1, + "name": "主题", + "children": [ + { + "level": 2, + "name": "章节", + "children": [ + { + "level": 3, + "name": "页面标题", + "children": [ + { + "level": 4, + "name": "内容标题" + } + ] + } + ] + } + ] + } +} +``` +> 状态:-1异常 1解析文件 3生成中 4完成 + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/generateOutline' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"subject": "AI未来的发展"}' +``` + +#### 修改大纲 + +根据用户指令修改大纲。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/ppt/updateOutline` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| outlineMarkdown | string | 是 | 大纲markdown内容 | +| length | string | 否 | 篇幅长度:short/medium/long, 默认medium, 分别对应: 10-15页/20-30页/25-35页 | +| question | string | 否 | 用户修改建议
系统内置:用金字塔原理优化、强化大纲结构和过渡、突出大纲主题、让大纲更专业
用户自定义:比如"帮我把大纲改成金字塔结构" | + +##### 响应 +event-stream,结构同generateOutline生成大纲。 + +#### 生成大纲内容 + +通过Markdown格式的大纲生成PPT内容。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/generateContent` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| stream | boolean | 否 | 是否流式生成(默认流式) | +| outlineMarkdown | string | 是 | 大纲markdown文本 | +| asyncGenPptx | boolean | 否 | 是否异步生成 | +| lang | string | 否 | 语言: zh/zh-Hant/en/ja/ko/ar/de/fr/it/pt/es/ru | +| prompt | string | 否 | 用户要求 | +| dataUrl | string | 否 | 文件数据url,调用解析文件内容接口返回 | + +##### 响应 +```json +{"text": "", "status": 3} +{"text": "#", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{ + "text": "", + "status": 4, + "result": { + "level": 1, + "name": "主题", + "children": [ + { + "level": 2, + "name": "章节", + "children": [ + { + "level": 3, + "name": "页面标题", + "children": [ + { + "level": 4, + "name": "内容标题", + "children": [ + { + "level": 0, + "name": "内容" + } + ] + } + ] + } + ] + } + ] + } +} +``` +> 状态:-1异常 1解析文件 3生成中 4完成 + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/generateContent' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"outlineMarkdown": "xxx"}' +``` + +#### 生成PPT + +通过大纲与内容生成PPT。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/generatePptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| templateId | string | 否 | 模板ID(非必填) | +| pptxProperty | boolean | 否 | 是否返回PPT数据结构 | +| outlineContentMarkdown | string | 是 | 大纲内容markdown | +| notes | array | 否 | 备注(PPT页面备注,非必填,数组["内容页面一备注", "内容页面二备注"]) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.pptInfo.id | string | ppt id | +| data.pptInfo.subject | string | 主题 | +| data.pptInfo.coverUrl | string | 封面 | +| data.pptInfo.fileUrl | string | PPT文件 | +| data.pptInfo.templateId | string | 模板ID | +| data.pptInfo.pptxProperty | string | PPT数据结构(json数据通过gzip压缩base64编码返回) | +| data.pptInfo.userId | string | 用户ID | +| data.pptInfo.userName | string | 用户名称 | +| data.pptInfo.companyId | number | 公司ID | +| data.pptInfo.updateTime | string/null | 更新时间 | +| data.pptInfo.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/generatePptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"outlineContentMarkdown": "xxx", "pptxProperty": false}' +``` + +### Word 转 PPT + +不同于通过解析文件生成PPT,Word转PPT会尽可能保留word文件中的层级结构和内容表述去生成PPT。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/v1/word2pptx` | +| 请求方法 | POST | +| Content-Type | `multipart/form-data` | + +##### 请求参数 +| 字段 | 类型 | 说明 | +|------|------|------| +| file | 文件 | docx文件(小于30M) | +| templateId | string | 模板ID(可空,为空时随机) | +| stream | boolean | 是否流式 | + +##### 非流式响应(application/json) +```json +{ + "code": 0, + "data": { + "pptInfo": { + "id": "xxx", + "subject": "xxx", + "coverUrl": "https://xxx.png", + "fileUrl": "https://xxx.pptx", + "templateId": "xxx", + "pptxProperty": "xxx", + "userId": "xxx", + "userName": "xxx", + "companyId": 1000, + "updateTime": null, + "createTime": "2024-01-01 10:00:00" + } + }, + "message": "操作成功" +} +``` + +##### 流式响应(event-stream) +```json +{"text": "", "status": 3} +{"text": "#", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{"text": "", "status": 3, "pptId": "xxx"} +{ + "text": "", + "status": 4, + "result": { + "id": "xxx", + "subject": "xxx", + "coverUrl": "https://xxx.png", + "fileUrl": "https://xxx.pptx", + "templateId": "xxx", + "pptxProperty": "xxx", + "userId": "xxx", + "userName": "xxx", + "companyId": 1000, + "updateTime": null, + "createTime": "2024-01-01 10:00:00" + } +} +``` +> 状态:-1异常 1解析文件 3生成中 4完成 + +##### 请求示例 +```bash +# 非流式 +curl -X POST --location 'https://open.docmee.cn/api/ppt/v1/word2pptx' \ +--header 'Content-Type: multipart/form-data' \ +--header 'token: {token}' \ +--form 'stream=false' \ +--form 'file=@test.docx;filename=test.docx' + +# 流式 +curl -X POST --location 'https://open.docmee.cn/api/ppt/v1/word2pptx' \ +--header 'Content-Type: multipart/form-data' \ +--header 'token: {token}' \ +--form 'stream=true' \ +--form 'file=@test.docx;filename=test.docx' +``` + +### 直接生成PPT + +直接让模型生成PPT。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/directGeneratePptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| stream | boolean | 否 | 是否流式生成 | +| templateId | string | 否 | 模板ID(非必填,为空则随机模板) | +| pptxProperty | boolean | 否 | 是否返回PPT数据结构 | +| length | string | 否 | 篇幅长度:short/medium/long, 默认medium, 分别对应: 10-15页/20-30页/25-35页 | +| lang | string | 否 | 语言: zh/zh-Hant/en/ja/ko/ar/de/fr/it/pt/es/ru | +| prompt | string | 否 | 用户要求(小于50字) | +| subject | string | 否 | 主题(与dataUrl可同时存在) | +| dataUrl | string | 否 | 文件数据url,调用解析文件内容接口返回(与subject可同时存在) | + +##### 非流式响应(application/json) +```json +{ + "code": 0, + "data": { + "pptInfo": { + "id": "xxx", + "subject": "xxx", + "coverUrl": "https://xxx.png", + "fileUrl": "https://xxx.pptx", + "templateId": "xxx", + "pptxProperty": "xxx", + "userId": "xxx", + "userName": "xxx", + "companyId": 1000, + "updateTime": null, + "createTime": "2024-01-01 10:00:00" + } + }, + "message": "操作成功" +} +``` + +##### 流式响应(event-stream) +```json +{"text": "", "status": 3} +{"text": "#", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{"text": "", "status": 3, "pptId": "xxx"} +{ + "text": "", + "status": 4, + "result": { + "id": "xxx", + "subject": "xxx", + "coverUrl": "https://xxx.png", + "fileUrl": "https://xxx.pptx", + "templateId": "xxx", + "pptxProperty": "xxx", + "userId": "xxx", + "userName": "xxx", + "companyId": 1000, + "updateTime": null, + "createTime": "2024-01-01 10:00:00" + } +} +``` +> 状态:-1异常 1解析文件 3生成中 4完成 + +##### 请求示例 +```bash +# 非流式 +curl -X POST --location 'https://open.docmee.cn/api/ppt/directGeneratePptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"stream": false, "subject": "AI未来的发展", "pptxProperty": false}' + +# 流式 +curl -X POST --location 'https://open.docmee.cn/api/ppt/directGeneratePptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"stream": true, "subject": "AI未来的发展", "pptxProperty": false}' +``` + +### AI PPT (异步) + +Ai异步流式生成PPT,只需在调用生成大纲接口后调用下面的generateContent接口即可生成PPT,无需再次调用生成PPT接口。 + +#### 生成大纲内容同时异步生成PPT + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/generateContent` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| templateId | string | 否 | 模板ID(非必填) | +| outlineMarkdown | string | 是 | 大纲markdown文本 | +| asyncGenPptx | boolean | 是 | 异步生成PPT(这里必须为true才会流式生成) | +| prompt | string | 否 | 用户要求 | +| dataUrl | string | 否 | 文件数据url,调用解析文件内容接口返回 | + +##### 响应 +```json +{"text": "", "status": 3, "pptId": "xxx", "total": 23, "current": 1} +{"text": "#", "status": 3} +{"text": " ", "status": 3} +{"text": "主题", "status": 3} +... +{ + "text": "", + "status": 4, + "result": { + "level": 1, + "name": "主题", + "children": [ + { + "level": 2, + "name": "章节", + "children": [ + { + "level": 3, + "name": "页面标题", + "children": [ + { + "level": 4, + "name": "内容标题", + "children": [ + { + "level": 0, + "name": "内容" + } + ] + } + ] + } + ] + } + ] + } +} +``` +> 状态:-1异常 0模型重置 1解析文件 2搜索网页 3生成中 4完成 + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/generateContent' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"outlineMarkdown":"xxx","asyncGenPptx":true}' +``` + +#### 查询异步生成PPT信息 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/asyncPptInfo?pptId=` | +| 请求方法 | GET | + +##### 参数 +**pptId** 为generateContent接口流式返回的pptId + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.total | number | 总页数 | +| data.current | number | 当前已生成页数(如果current >= total时表示PPT生成完成) | +| data.pptxProperty | string | PPT数据结构(json gzip base64) | +| code | number | 状态码 | + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/ppt/asyncPptInfo?pptId=xxx' \ +--header 'token: {token}' +``` + +> **说明**:该接口不需要轮询,在generateContent接口流式返回pptId数据时调用,每出现一次pptId就调用一次获取最新的PPT信息。 +> +> **注意**:这个接口只有在流式生成过程中能查询到数据(临时缓存数据),在PPT生成完成的30秒内过期(查不到数据),此时需要调用loadPptx加载PPT数据接口查询。 + +### 对话生成PPT + +兼容openai chat接口生成PPT,鉴权支持请求头Api-Key和Authorization Bearer两种方式。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt-openai/v1/chat/completions` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| stream | boolean | 否 | 是否流式 | +| model | string | 是 | 模型(固定:direct-generate-pptx) | +| messages | array | 是 | 消息体:不支持连续对话(多个时默认取最后一个user) | +| appendLink | boolean | 否 | 大纲内容生成完成后是否在文本后面追加封面图片和下载链接(默认true) | +| templateId | string | 否 | 模板ID(默认为null,系统随机) | +| lang | string | 否 | 语言: zh/zh-Hant/en/ja/ko/ar/de/fr/it/pt/es/ru | +| prompt | string | 否 | 用户要求(不超过50字) | + +messages结构: +```json +[ + { + "role": "user", + "content": "AI未来的发展" + } +] +``` +> 支持:主题、文档内容、文件链接(公网可访问) + +##### 非流式响应(application/json) +```json +{ + "id": "1833839690764124160", + "model": "direct-generate-pptx", + "choices": [ + { + "index": 0, + "finish_reason": "stop", + "message": { + "role": "assistant", + "content": "# AI未来的发展\\n## 1 技术进步\\n### 1.1 算法优化\\n#### 1.1.1 深度学习\\n- 深度学习模型不断优化,提高准确性和效率...|\\n\\n[封面图片]\\n\\n[点击下载]" + }, + "ppt_data": { + "id": "1833839690764124160", + "subject": "AI未来的发展", + "templateId": "xxx", + "coverUrl": "https://xxx.png", + "fileUrl": "https://xxx.pptx" + } + } + ], + "object": "chat.completion", + "created": 1726056513, + "usage": { + "completion_tokens": 10000, + "prompt_tokens": 2000, + "total_tokens": 12000 + } +} +``` + +##### 流式响应(event-stream) +```text +data: {"id":"1833839690764124160","choices":[{"delta":{"content":"#","role":"assistant"},"finish_reason":null,"index":0}],"created":1726056518,"model":"direct-generate-pptx","object":"chat.completion.chunk"} +data: {"id":"1833839690764124160","choices":[{"delta":{"content":" ","role":"assistant"},"finish_reason":null,"index":0}],"created":1726056518,"model":"direct-generate-pptx","object":"chat.completion.chunk"} +data: {"id":"1833839690764124160","choices":[{"delta":{"content":"AI","role":"assistant"},"finish_reason":null,"index":0}],"created":1726056518,"model":"direct-generate-pptx","object":"chat.completion.chunk"} +... +data: {"id":"1833839690764124160","choices":[{"delta":{"content":null,"role":"assistant"},"finish_reason":"stop","index":0,"ppt_data":{"companyId":1000,"coverUrl":"https://xxx.png","createTime":1726056519624,"fileUrl":"https://xxx.pptx","id":"1833839690764124160","name":"AI未来的发展","subject":"AI未来的发展","templateId":"1815308477845987328","updateTime":1726056519624,"userId":"xxx","userName":"xxx"}}],"created":1726056529,"model":"direct-generate-pptx","object":"chat.completion.chunk"} +``` + +##### Python请求示例 +```python +import json +from openai import OpenAI + +if __name__ == '__main__': + # 通过openai库直接请求 + client = OpenAI(base_url='{域名}/api/ppt-openai/v1', api_key='sk-xxx') + # 是否流式请求 + stream = True + response = client.chat.completions.create( + timeout=120, + stream=stream, + model='direct-generate-pptx', + messages=[ + { + 'role': 'user', + 'content': 'AI未来的发展' + } + ] + ) + if stream: + # 流式 + for trunk in response: + choice = trunk['choices'][0] + print(choice['delta']['content'], end='') + if 'ppt_data' in choice: + print(json.dumps(choice['ppt_data'])) + else: + # 非流式 + choice = response['choices'][0] + print(choice['message']['content']) + if 'ppt_data' in choice: + print(json.dumps(choice['ppt_data'])) +``` + +### MCP + +兼容Model Context Protocol(MCP)生成PPT。 + +| 属性 | 说明 | +|------|------| +| SSE Server端点 | `/api/mcp/sse?token=` | +| 鉴权 | 通过URL上的token参数鉴权,设置为你在平台的Api-Key或通过接口创建的token | + +#### tools/list +```json +[ + { + "name": "ai_generate_ppt", + "description": "AI generate PPT", + "inputSchema": { + "type": "object", + "properties": { + "task_description": { + "type": "string" + } + }, + "required": ["task_description"], + "additionalProperties": false + } + } +] +``` + +#### Typescript接入示例 +```typescript +import { Client } from '@modelcontextprotocol/sdk/client/index.js' +import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js' + +async function main() { + const apiKey = 'ak_xxx' + const mcpClient = new Client({ + name: 'mcp-client-test', + version: '1.0.0', + }) + const transport = new SSEClientTransport( + new URL('https://open.docmee.cn/api/mcp/sse?token=' + apiKey), + ) + mcpClient.connect(transport) + const toolsResult = await mcpClient.listTools() + console.log('Tools:', toolsResult) + const result = await mcpClient.callTool({ + name: 'ai_generate_ppt', + arguments: { + task_description: '请以AI未来的发展为主题生成PPT', + }, + }) + console.log('Result:', result) +} + +main() +``` + +## 模板管理 + +### 获取模板过滤选项 + +获取查询模版的过滤选项。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/template/options` | +| 请求方法 | GET | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.category | array | 类目筛选 | +| data.style | array | 风格筛选 | +| data.themeColor | array | 主题颜色筛选 | +| code | number | 状态码 | +| message | string | 提示信息 | + +**类目(category)筛选**: +1. {name: "全部", value: ""} +2. {name: "年终总结", value: "年终总结"} +3. {name: "教育培训", value: "教育培训"} +4. {name: "医学医疗", value: "医学医疗"} +5. {name: "商业计划书", value: "商业计划书"} +6. {name: "企业介绍", value: "企业介绍"} +7. {name: "毕业答辩", value: "毕业答辩"} +8. {name: "营销推广", value: "营销推广"} +9. {name: "晚会表彰", value: "晚会表彰"} +10. {name: "个人简历", value: "个人简历"} + +**风格(style)筛选**: +1. {name: "全部", value: ""} +2. {name: "扁平简约", value: "扁平简约"} +3. {name: "商务科技", value: "商务科技"} +4. {name: "文艺清新", value: "文艺清新"} +5. {name: "卡通手绘", value: "卡通手绘"} +6. {name: "中国风", value: "中国风"} +7. {name: "创意时尚", value: "创意时尚"} +8. {name: "创意趣味", value: "创意趣味"} + +**主题颜色(themeColor)筛选**: +1. {name: "全部", value: ""} +2. {name: "橙色", value: "#FA920A"} +3. {name: "蓝色", value: "#589AFD"} +4. {name: "紫色", value: "#7664FA"} +5. {name: "青色", value: "#65E5EC"} +6. {name: "绿色", value: "#61D328"} +7. {name: "黄色", value: "#F5FD59"} +8. {name: "红色", value: "#E05757"} +9. {name: "棕色", value: "#8F5A0B"} +10. {name: "白色", value: "#FFFFFF"} +11. {name: "黑色", value: "#000000"} + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/ppt/template/options' +``` + +### 分页查询PPT模板 + +分页查询PPT模版。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/templates` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| page | number | 是 | 分页:第几页 | +| size | number | 是 | 分页:每页大小 | +| filters.type | number | 是 | 模板类型(必传):1系统模板、4用户自定义模板 | +| filters.category | string | 否 | 类目筛选 | +| filters.style | string | 否 | 风格筛选 | +| filters.themeColor | string | 否 | 主题颜色筛选 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| total | number | 总数 | +| data[].id | string | 模板ID | +| data[].type | number | 模板类型:1大纲完整PPT、4用户模板 | +| data[].coverUrl | string | 封面(需要拼接?token=${token}访问) | +| data[].category | string/null | 类目 | +| data[].style | string/null | 风格 | +| data[].themeColor | string/null | 主题颜色 | +| data[].subject | string | 主题 | +| data[].num | number | 模板页数 | +| data[].createTime | string | 创建时间 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/templates' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"page": 1, "size":10, "filters": { "type": 1 }}' +``` + +> **注意**: +> - 封面图片资源访问,需要在url上拼接`?token=xxx` +> - 模板接口支持国际化,在请求URL上传lang参数,示例:/api/ppt/templates?lang=zh-CN +> - 国际化语种支持:zh,zh-Hant,en,ja,ko,ar,de,fr,it,pt,es,ru + +### 随机PPT模板 + +随机获取若干数量的PPT模版。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/randomTemplates` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| size | number | 是 | 数量 | +| filters.type | number | 是 | 模板类型(必传):1系统模板、4用户自定义模板 | +| filters.category | string | 否 | 类目 | +| filters.style | string | 否 | 风格 | +| filters.themeColor | string | 否 | 主题颜色 | +| filters.neq_id | array | 否 | 排查ID集合(把之前查询返回的id排除) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| total | number | 总数 | +| data[].id | string | 模板ID | +| data[].type | number | 模板类型:1大纲完整PPT、4用户模板 | +| data[].coverUrl | string | 封面(需要拼接?token=${token}访问) | +| data[].category | string/null | 类目 | +| data[].style | string/null | 风格 | +| data[].themeColor | string/null | 主题颜色 | +| data[].subject | string | 主题 | +| data[].num | number | 模板页数 | +| data[].createTime | string | 创建时间 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/randomTemplates' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"size":10, "filters": { "type": 1 }}' +``` + +> **注意**: +> - 封面图片资源访问,需要在url上拼接`?token=xxx` +> - 模板接口支持国际化,在请求URL上传lang参数,示例:/api/ppt/randomTemplates?lang=zh-CN +> - 国际化语种支持:zh,zh-Hant,en,ja,ko,ar,de,fr,it,pt,es,ru + +## PPT获取与操作 + +### 获取PPT列表 + +分页查询您的PPT作品列表。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/listPptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| page | number | 是 | 分页:第几页 | +| size | number | 是 | 分页:每页大小 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| total | number | 总数 | +| data[].id | string | ppt id | +| data[].subject | string | 主题 | +| data[].coverUrl | string | 封面 | +| data[].templateId | string | 模板ID | +| data[].userId | string | 用户ID | +| data[].userName | string | 用户名称 | +| data[].companyId | number | 公司ID | +| data[].updateTime | string/null | 更新时间 | +| data[].createTime | string | 创建时间 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/listPptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"page": 1, "size": 10}' +``` + +### 加载PPT数据 + +加载一个PPT的完整数据内容。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/loadPptx?id=` | +| 请求方法 | GET | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.pptInfo.id | string | ppt id | +| data.pptInfo.subject | string | 主题 | +| data.pptInfo.coverUrl | string | 封面 | +| data.pptInfo.templateId | string | 模板ID | +| data.pptInfo.pptxProperty | string | PPT数据结构(json数据通过gzip压缩base64编码返回) | +| data.pptInfo.userId | string | 用户ID | +| data.pptInfo.userName | string | 用户名称 | +| data.pptInfo.companyId | number | 公司ID | +| data.pptInfo.updateTime | string/null | 更新时间 | +| data.pptInfo.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/ppt/loadPptx?id=xxx' \ +--header 'token: {token}' +``` + +### 加载PPT大纲内容 + +获取生成PPT所使用的大纲内容。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/loadPptxMarkdown` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | pptId | +| format | string | 是 | 输出格式:text大纲文本;tree大纲结构树 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.markdownText | string | 大纲markdown文本(当format为text时返回) | +| data.markdownTree | object | 大纲结构树(当format为tree时返回) | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/loadPptxMarkdown' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id": "xxx", "format": "tree"}' +``` + +### 下载PPT + +下载PPT到本地。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/downloadPptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | pptId | +| refresh | boolean | 否 | 是否刷新(默认false) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.id | string | pptId | +| data.name | string | 名称 | +| data.subject | string | 主题 | +| data.fileUrl | string | 文件链接(有效期:2小时) | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/downloadPptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx"}' +``` + +### 下载-智能动画PPT + +给PPT自动加上动画再下载到本地。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/downloadWithAnimation?type=1&id=xxx` | +| 请求方法 | GET | + +##### URL请求参数 +| 参数 | 类型 | 描述 | +|------|------|------| +| type | number | 动画类型,1依次展示(默认);2单击展示 | +| id | string | PPT ID | + +##### 响应 +application/octet-stream 文件数据流 + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/ppt/downloadWithAnimation?type=1&id=xxx' \ +--header 'token: {token}' +``` + +> **注意**: +> - 该接口会在原有的PPT元素对象上智能添加动画效果(元素入场动画 & 页面切场动画) +> - 动画类型介绍: +> - 1 依次展示,表示上一个元素动画结束后立马展示下一个元素动画 +> - 2 单击展示,表示在内容页,上一项内容展示完成后需要单击才会展示下一项内容,其他页面效果同依次展示。 + +### 更换PPT模板 + +更换PPT的模板。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/updatePptTemplate` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| pptId | string | 是 | ppt id | +| templateId | string | 是 | 模板ID | +| sync | boolean | 否 | 是否同步更新PPT文件(默认false异步更新,速度快) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.pptId | string | pptId | +| data.templateId | string | 模板ID | +| data.pptxProperty | object | 更换后的pptx结构数据(json) | +| code | number | 状态码 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/updatePptTemplate' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"pptId":"xxx","templateId":"xxx","sync":false}' +``` + +### 更新PPT属性 + +修改PPT的名称或主题。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/updatePptxAttr` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | ppt id | +| name | string | 否 | 名称(不能为空则修改) | +| subject | string | 否 | 主题(不能为空则修改) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/updatePptxAttr' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx","name":"xxx"}' +``` + +### 设置Logo + +设置PPT的LOGO。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/addPptLogo` | +| 请求方法 | POST | +| Content-Type | `multipart/form-data` | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| pptId | string | 是 | PPT ID | +| image | File | 是 | Logo图片文件(png / jpg) | +| position | string | 是 | Logo位置:`TOP_LEFT`、`TOP_CENTER`、`TOP_RIGHT`、`BOTTOM_LEFT`、`BOTTOM_CENTER`、`BOTTOM_RIGHT` | +| pageIndex | integer | 否 | 指定页码(从1开始) | +| pageTypes | number[] | 否 | 指定页面类型数组 | +| marginX | number | 否 | X方向边距 | +| marginY | number | 否 | Y方向边距 | +| scale | number | 是 | Logo缩放比例 | +| rmOrgLogo | boolean | 是 | 是否移除原有Logo | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.fileUrl | string | pptx文件下载地址 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/addPptLogo' \ +--header 'Content-Type: multipart/form-data' \ +--header 'token: {token}' \ +--form 'pptId=12354768' \ +--form 'image=@test.png;filename=test.png' \ +--form 'position=TOP_RIGHT' \ +--form 'scale=1' \ +--form 'rmOrgLogo=true' \ +--form 'marginX=0' \ +--form 'marginY=0' +``` + +### 移除Logo + +移除PPT的LOGO。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/removePptLogo` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| pptId | string | 是 | PPT ID | +| pageIndex | integer | 否 | 指定页码(从1开始) | +| pageTypes | number[] | 否 | 指定页面类型数组 0:首页, 1:目录页, 2:章节页, 3:内容页, 4:尾页 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/removePptLogo' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"pptId":"12354768","pageIndex":1,"pageTypes":[1,2]}' +``` + +### 保存PPT + +保存PPT的修改。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/savePptx` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | ppt id | +| drawPptx | boolean | 否 | 是否重新渲染PPT文件并上传 | +| drawCover | boolean | 否 | 是否重新渲染PPT封面并上传 | +| pptxProperty | object | 否 | 修改过后的pptx页面数据结构树 | + +> 如果您只想要重新渲染ppt,您可以传递drawPptx为true。这时您可以传递最新的pptxProperty结构来渲染,如果您没有最新的pptxProperty结构,该字段请不要传递,留空即可。 + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.pptInfo | object | ppt信息(数据同generatePptx生成PPT接口结构) | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/savePptx' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx","drawPptx":true,"drawCover":true,"pptxProperty":{}}' +``` + +### 删除PPT + +删除指定的PPT。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/delete` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | ppt id | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/delete' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id":"xxx"}' +``` + +## 自定义模板 + +### 上传用户自定义模板 + +上传用户自定义的PPT模板。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/uploadTemplate` | +| 请求方法 | POST | +| Content-Type | `multipart/form-data` | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| type | int | 是 | 类型,用户自定义模板传4(写死) | +| file | File | 是 | 文件(仅支持pptx,幻灯片大小960x540) | +| templateId | string | 否 | 模板ID(更新时传,会覆盖该模板) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.id | string | 模板ID | +| data.type | number | 模板类型:4用户模板 | +| data.coverUrl | string | 封面(需要拼接token才能访问) | +| data.subject | string | 主题 | +| data.pptxProperty | string | PPT数据结构(json gzip base64) | +| data.num | number | 页码 | +| data.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/uploadTemplate' \ +--header 'Content-Type: multipart/form-data' \ +--header 'token: {token}' \ +--form 'type=4' \ +--form 'file=@test.doc;filename=test.doc' +``` + +> **注意**: +> - 模板标准幻灯片大小(16:9)960x540 (33.867x19.05厘米),如果尺寸非标准大小,可在microsoft office中修改步骤:设计 > 幻灯片大小 > 自定义幻灯片大小 => 33.867x19.05厘米 +> - 上传用户自定义模板后,AI会自动标注学习,如果您觉得生成效果有问题,对不上,可以访问下面链接手动纠正AI标注结果:[https://docmee.cn/marker/{templateId}?token={apiKey}](https://docmee.cn/marker/%5C%7BtemplateId%5C%7D?token=%5C%7BapiKey%5C%7D) 请把{templateId}替换成真实的模板ID,{apiKey}替换成你的api-key,示例: +> - 注意:如果是覆盖公共模板,请把token换成Api-Key调用,不然无权限访问。 + +### 下载自定义模板 + +下载用户自定义的模板。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/downloadTemplate` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 模板ID | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.id | string | 模板ID | +| data.subject | string | 主题 | +| data.type | number | 模板类型:4用户模板 | +| data.coverUrl | string | 封面(需要拼接token才能访问) | +| data.fileUrl | string | 模板下载地址(可直接访问) | +| data.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/downloadTemplate' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id": "xxx"}' +``` + +### 删除自定义模板 + +删除用户自定义的模板。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/delTemplateId` | +| 请求方法 | POST | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 模板ID | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/delTemplateId' \ +--header 'Content-Type: application/json' \ +--header 'token: {token}' \ +--data '{"id": "xxx"}' +``` + +### 修改模版属性(名称) + +修改自定义模版的信息(名称)。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/updateTemplate` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| id | string | 是 | 模板Id | +| name | string | 是 | 模板名称 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/updateTemplate' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: {apiKey}' \ +--data '{"id": "xxx", "name": "测试修改111"}' +``` + +### 设置为公共模板 + +将自定义模版设置为Api-Key账号级别的公共模板,但并非平台公共模板。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/updateUserTemplate` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| templateId | string | 是 | 模板ID | +| isPublic | boolean | 是 | 是否公开(true公开,API-KEY下创建的所有token可以看到) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/updateUserTemplate' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: {apiKey}' \ +--data '{"templateId": "xxx", "isPublic": true}' +``` + +## 积分和使用记录 + +### 查询API信息 + +获取当前用户的积分使用情况。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/user/apiInfo` | +| 请求方法 | GET | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.availableCount | number | 可用次数 | +| data.usedCount | number | 已使用次数 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/user/apiInfo' \ +--header 'Api-Key: xxx' +``` + +### 查询积分使用记录 + +获取一段时间内的积分使用记录。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/record/listPage` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| page | number | 是 | 分页:第几页 | +| size | number | 是 | 分页:每页大小 | +| type | number | 否 | 类型:1 PPT生成;2 模板上传;(默认全部) | +| uid | string | 否 | 第三方用户ID | +| startDate | string | 是 | 查询开始时间(必须) | +| endDate | string | 是 | 查询结束时间(必须) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| total | number | 总数 | +| data[].id | string | 记录ID(ppt ID或模板ID) | +| data[].type | number | 记录类型:1 ppt生成; 2 模板上传 | +| data[].amount | number | 消耗积分 | +| data[].uid | string | 第三方用户ID | +| data[].createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/record/listPage' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: xxx' \ +--data '{ "page": 1, "size": 100, "type": 1, "startDate": "2025-01-01", "endDate": "2025-12-31" }' +``` + +### 查询记录详情 + +获取一条积分使用记录的详细信息。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/record/getById?id=` | +| 请求方法 | GET | + +##### 参数 +id参数: 记录ID + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data.id | string | PPT Id或模板ID | +| data.name | string | 名称 | +| data.subject | string | 主题 | +| data.coverUrl | string | 封面图(需在URL拼接token才能访问) | +| data.fileUrl | string | pptx文件(需在URL拼接token才能访问) | +| data.templateId | string | type=1的PPT记录才有templateId字段 | +| data.userId | string | 用户ID | +| data.userName | string | 用户名称 | +| data.updateTime | string | 修改时间 | +| data.createTime | string | 创建时间 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X GET --location 'https://open.docmee.cn/api/record/getById?id=xxx' \ +--header 'Api-Key: xxx' +``` + +### 按小时统计积分使用 + +按小时统计积分使用情况。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/record/statisticHours` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| type | number | 否 | 类型:1 生成PPT;2 上传模板;默认全部 | +| uid | string | 否 | 第三方用户ID | +| date | string | 是 | 日期(必须) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data[].count | number | 使用次数 | +| data[].hour | number | 时间-小时整点(0-24) | +| data[].amount | number | 消耗积分数 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/record/statisticHours' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: xxx' \ +--data '{ "type": 1, "date": "2025-01-01" }' +``` + +### 按天统计积分使用 + +按天统计积分使用情况。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/record/statisticDays` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| type | number | 否 | 类型:1 生成PPT;2 上传模板;默认全部 | +| uid | string | 否 | 第三方用户ID | +| startDate | string | 是 | 查询开始时间(必须) | +| endDate | string | 是 | 查询结束时间(必须) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| data[].count | number | 使用次数 | +| data[].date | string | 日期 | +| data[].amount | number | 消耗积分 | +| code | number | 状态码 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/record/statisticDays' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: xxx' \ +--data '{ "type": 1, "startDate": "2025-01-01", "endDate": "2025-12-31" }' +``` + +### 查询所有PPT列表 + +获取当前Api-Key下一段时间内所有生成的PPT文件。 + +| 属性 | 说明 | +|------|------| +| 接口地址 | `https://open.docmee.cn/api/ppt/listAllPptx` | +| 请求方法 | POST | + +##### 请求头 +| 头部 | 说明 | +|------|------| +| Api-Key | 在开放平台获取 | + +##### 请求参数 +| 参数 | 类型 | 是否必传 | 说明 | +|------|------|----------|------| +| page | number | 是 | 分页 | +| size | number | 是 | 每页大小(最大不超过100) | +| id | string | 否 | ppt id(非必填) | +| uid | string | 否 | 第三方用户ID(非必填) | +| templateId | string | 否 | 模板ID(非必填) | +| startDate | string | 否 | 创建开始时间(非必填) | +| endDate | string | 否 | 创建结束时间(非必填) | +| desc | boolean | 否 | 按时间倒序返回(非必填) | + +##### 响应参数 +| 参数 | 类型 | 说明 | +|------|------|------| +| code | number | 状态码 | +| total | number | 总数 | +| data[].id | string | ppt id | +| data[].subject | string | 主题 | +| data[].coverUrl | string | 封面(需要拼接?token={API-KEY}访问) | +| data[].fileUrl | string | 文件(需要拼接?token={API-KEY}访问) | +| data[].templateId | string | 模板ID | +| data[].userId | string | 用户ID / uid | +| data[].companyId | number | 公司ID | +| data[].createTime | string | 创建时间 | +| message | string | 提示信息 | + +##### 请求示例 +```bash +curl -X POST --location 'https://open.docmee.cn/api/ppt/listAllPptx' \ +--header 'Content-Type: application/json' \ +--header 'Api-Key: xxx' \ +--data '{"page": 1, "size": 10}' +``` + +## 错误码 + +### 接口application/json错误 +```json +{ + "code": 0, + "message": "操作成功" +} +``` + +| 错误码 | 说明 | +|-------|------| +| 0 | 操作成功(正常) | +| -1 | 操作失败(未知错误) | +| 88 | 功能受限(积分已用完或非VIP) | +| 98 | 认证失败(检查token是否过期) | +| 99 | 登录过期 | +| 1001 | 数据不存在 | +| 1002 | 数据访问异常 | +| 1003 | 无权限访问 | +| 1006 | 内容涉及敏感信息 | +| 1009 | AI服务异常 | +| 1010 | 参数错误 | +| 1012 | 请求太频繁,限流 | + +### SEE流式请求错误 + +初始化流式调用时发生错误会返回application/json错误信息: +```json +{ + "code": 1010, + "message": "参数错误:name不能为空" +} +``` + +流式过程中遇到错误,会在流中返回text/event-stream流式错误信息: +```text +data: {"status":-1, "error":"AI模型执行异常"} +``` + +## 特殊说明 + +### PPT前端渲染 + +关于ppt数据结构在前端渲染问题,我们已经把前端代码开源到github: + +- +- +- + +### Markdown规范 + +适用于调用方需要通过自己内容和模型生成PPT内容,调用方根据我们的规范生成markdown内容,然后调用接口合成PPT。 + +#### 规范示例 +```markdown +# 主题 + +## 章节 + +### 页面标题 + +#### 内容标题一 + +这是文本内容... +![图片一](https://xxx.png) + +#### 内容标题二 + +这是文本内容... +![图片二](https://xxx.png) +``` + +#### 规范说明 +- `# 主题`(一级标题,必须包含,只能有一个) +- `## 章节一`(二级标题,目录章节,必须包含,建议6个章节左右) +- `### 页面一`(三级标题,页面标题,每个章节下建议3个左右,30字以内) +- `#### 段落标题一`(四级标题,段落标题,每个页面下建议3个左右,30字以内) +- `- 段落文本内容`(内容长度建议在40-80字之间) + +表格支持: +```markdown +| 季度 | 销售额 | +| -------- | ------ | +| 第一季度 | 380.0 | +| 第二季度 | 826.5 | +| 第三季度 | 512.2 | +| 第四季度 | 674.0 | +``` + +> markdown规范没有定这么死,除了主题(一级标题)和章节(二级标题)必须包含外,其他标题可以没有。 + +完整markdown示例下载:[markdown.md](https://metasign-public.oss-cn-shanghai.aliyuncs.com/docmee/markdown.md) + +生成markdown后,调用generatePptx生成PPT接口,对应outlineContentMarkdown参数。 + +### 接入示例 + +官方提供了多种语言的接入示例: + +- UI接入示例V2: +- UI接入示例V1: +- Python Api接入示例: +- Java Api接入示例: +- Go Api接入示例: +- PHP Api接入示例: + +### PPT生成方式说明 + +官方最推荐使用**版本2**来创作PPT,也是官方应用[文多多AiPPT](https://docmee.cn)中使用的方式。 + +#### 版本2(官方推荐) +1. 调用`createTask`创建任务 +2. 调用`generateContent`生成大纲内容 +3. 调用`generatePptx`生成PPT + +#### 直接生成PPT +- 调用`directGeneratePptx`直接生成PPT接口,支持流式和非流式 + +#### 实时流式生成PPT(版本1) +1. 调用`generateOutline`生成大纲 +2. 调用`generateContent`生成大纲内容同时异步生成PPT +3. 在第二步中接收实时流式json数据过程中判断是否有pptId,存在时调用`asyncPptInfo`获取进度 + +#### 同步流式生成PPT(版本1) +1. 调用`generateOutline`生成大纲 +2. 调用`generateContent`生成大纲内容 +3. 调用`generatePptx`生成PPT + +#### openai chat方式生成PPT +- 调用`/chat/completions`OpenAi-对话生成PPT接口 + +#### 通过markdown生成PPT +- 集成方生成markdown内容,然后调用`generatePptx`生成PPT + +#### MCP +- 兼容Model Context Protocol(MCP)生成PPT \ No newline at end of file diff --git a/_tmp_docmee_aippt_vue b/_tmp_docmee_aippt_vue new file mode 160000 index 0000000..c9bc73c --- /dev/null +++ b/_tmp_docmee_aippt_vue @@ -0,0 +1 @@ +Subproject commit c9bc73c815bb02ad77d84e2d8fa5f52abc892398 diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/.gitignore b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/.gitignore new file mode 100644 index 0000000..daf4db9 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/ +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README.md b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README.md new file mode 100644 index 0000000..2ffb53b --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README.md @@ -0,0 +1,69 @@ +

logo

+

文多多 AiPPT

+

+ 简体中文 | English +

+

+ 🔗在线演示 +   •   + 📝PPT转JSON +   •   + 🌏官方网站 +   •   + 💬合作交流 +

+ + + + + +# 🤖 AI 生成 PPT + +商用级 AI 生成 PPT 项目,包含以下功能: + +* AI 生成 PPT +* PPT 解析成 JSON +* JSON 反渲染为 PPT + + + +# ✨ AiPPT + +在线体验:https://veasion.github.io/aippt + + +[演示视频](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/aippt.mp4) + +https://github.com/veasion/aippt/assets/24989778/24d5654b-09f3-4554-a732-dbffc1073a1d + + + +# ✨ PPT 解析成 JSON + +支持上传PPT并渲染,在线编辑,编辑后下载 ppt 文件。 + +在线体验:https://veasion.github.io/aippt/ppt2json.html + + + + + + + + +# 🤝 商业合作 + +针对上面技术,我们开发了一套可商用 aippt 软件,支持代理 & 私有化部署! + +我们的优势,支持定制化行业解决方案,支持原生图表、动画等复杂PPT解析和渲染,支持用户自定义模板,技术方案行业领先,价格行业最低。 + +官网地址(开放API): +https://docmee.cn + +开放平台(API/UI 接入): +https://docmee.cn/open-platform + + +商业合作 & 进群交流: + +![qrcode](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/contact_me_qr.png) diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README_EN.md b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README_EN.md new file mode 100644 index 0000000..ccc2256 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/README_EN.md @@ -0,0 +1,69 @@ +

logo

+

Docmee AiPPT

+

+ English | 简体中文 +

+

+ 🔗Demo +   •   + 📝PPT to JSON +   •   + 🌏Official website +   •   + 💬Business cooperation +

+ + + + + +# 🤖 AI Generate PPT + +Commercial level AI generated PPT project, including the following features: + +* AI generated PPT +* PPT parsed into JSON +* JSON re-rendered as PPT + + + +# ✨ AiPPT + +Demo: https://veasion.github.io/aippt + +[Demo Video](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/aippt.mp4) + +https://github.com/veasion/aippt/assets/24989778/24d5654b-09f3-4554-a732-dbffc1073a1d + + + +# ✨ PPT to JSON + +Support uploading PPT and rendering, online editing, and download the edited PPT file. + +Demo: https://veasion.github.io/aippt/ppt2json.html + + + + + + + + +# 🤝 Business cooperation + +We have developed a commercially available aippt software that supports proxy and private deployment for the above technology! + +Our advantages include supporting customized industry solutions, supporting complex PPT analysis and rendering such as native charts and animations, supporting user-defined templates, leading technology solutions, and the lowest prices in the industry. + +Official website (Open API): +https://docmee.cn + +Open platform (API / UI): +https://docmee.cn/open-platform + + +WeChat group qrcode: + +![qrcode](https://metasign-public.oss-cn-shanghai.aliyuncs.com/github/contact_me_qr.png) + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/env.d.ts b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/index.html b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/index.html new file mode 100644 index 0000000..758ef6f --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/index.html @@ -0,0 +1,13 @@ + + + + + + + 文多多AiPPT + + +
+ + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package-lock.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package-lock.json new file mode 100644 index 0000000..6224b4c --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package-lock.json @@ -0,0 +1,1380 @@ +{ + "name": "aippt-vue", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "aippt-vue", + "version": "1.0.0", + "dependencies": { + "@types/pako": "^2.0.3", + "base64-js": "^1.5.1", + "marked": "^13.0.2", + "pako": "^2.1.0", + "vue": "^3.4.29" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.2.0", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://r.cnpmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://r.cnpmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tsconfig/node20": { + "version": "20.1.4", + "resolved": "https://r.cnpmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz", + "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://r.cnpmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.11", + "resolved": "https://r.cnpmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/pako": { + "version": "2.0.3", + "resolved": "https://r.cnpmjs.org/@types/pako/-/pako-2.0.3.tgz", + "integrity": "sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q==" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.5", + "resolved": "https://r.cnpmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz", + "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.0-alpha.16", + "resolved": "https://r.cnpmjs.org/@volar/language-core/-/language-core-2.4.0-alpha.16.tgz", + "integrity": "sha512-oOTnIZlx0P/idFwVw+W0NbzKDtZAQMzXSdIFfTePCKcXlb4Ys12GaGkx8NF9dsvPYV3nbv3ZsSxnkZWBmNKd7A==", + "dev": true, + "dependencies": { + "@volar/source-map": "2.4.0-alpha.16" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.0-alpha.16", + "resolved": "https://r.cnpmjs.org/@volar/source-map/-/source-map-2.4.0-alpha.16.tgz", + "integrity": "sha512-sL9vNG7iR2hiKZor7UkD5Sufu3QCia4cbp2gX/nGRNSdaPbhOpdAoavwlBm0PrVkpiA19NZuavZoobD8krviFg==", + "dev": true + }, + "node_modules/@volar/typescript": { + "version": "2.4.0-alpha.16", + "resolved": "https://r.cnpmjs.org/@volar/typescript/-/typescript-2.4.0-alpha.16.tgz", + "integrity": "sha512-WCx7z5O81McCQp2cC0c8081y+MgTiAR2WAiJjVL4tr4Qh4GgqK0lgn3CqAjcKizaK1R5y3wfrUqgIYr+QeFYcw==", + "dev": true, + "dependencies": { + "@volar/language-core": "2.4.0-alpha.16", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/compiler-core/-/compiler-core-3.4.32.tgz", + "integrity": "sha512-8tCVWkkLe/QCWIsrIvExUGnhYCAOroUs5dzhSoKL5w4MJS8uIYiou+pOPSVIOALOQ80B0jBs+Ri+kd5+MBnCDw==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.32", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.32.tgz", + "integrity": "sha512-PbSgt9KuYo4fyb90dynuPc0XFTfFPs3sCTbPLOLlo+PrUESW1gn/NjSsUvhR+mI2AmmEzexwYMxbHDldxSOr2A==", + "dependencies": { + "@vue/compiler-core": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.32.tgz", + "integrity": "sha512-STy9im/WHfaguJnfKjjVpMHukxHUrOKjm2vVCxiojQJyo3Sb6Os8SMXBr/MI+ekpstEGkDONfqAQoSbZhspLYw==", + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.32", + "@vue/compiler-dom": "3.4.32", + "@vue/compiler-ssr": "3.4.32", + "@vue/shared": "3.4.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.39", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.32.tgz", + "integrity": "sha512-nyu/txTecF6DrxLrpLcI34xutrvZPtHPBj9yRoPxstIquxeeyywXpYZrQMsIeDfBhlw1abJb9CbbyZvDw2kjdg==", + "dependencies": { + "@vue/compiler-dom": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/language-core": { + "version": "2.0.26", + "resolved": "https://r.cnpmjs.org/@vue/language-core/-/language-core-2.0.26.tgz", + "integrity": "sha512-/lt6SfQ3O1yDAhPsnLv9iSUgXd1dMHqUm/t3RctfqjuwQf1LnftZ414X3UBn6aXT4MiwXWtbNJ4Z0NZWwDWgJQ==", + "dev": true, + "dependencies": { + "@volar/language-core": "~2.4.0-alpha.15", + "@vue/compiler-dom": "^3.4.0", + "@vue/shared": "^3.4.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/reactivity/-/reactivity-3.4.32.tgz", + "integrity": "sha512-1P7QvghAzhSIWmiNmh4MNkLVjr2QTNDcFv2sKmytEWhR6t7BZzNicgm5ENER4uU++wbWxgRh/pSEYgdI3MDcvg==", + "dependencies": { + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/runtime-core/-/runtime-core-3.4.32.tgz", + "integrity": "sha512-FxT2dTHUs1Hki8Ui/B1Hu339mx4H5kRJooqrNM32tGUHBPStJxwMzLIRbeGO/B1NMplU4Pg9fwOqrJtrOzkdfA==", + "dependencies": { + "@vue/reactivity": "3.4.32", + "@vue/shared": "3.4.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.32.tgz", + "integrity": "sha512-Xz9G+ZViRyPFQtRBCPFkhMzKn454ihCPMKUiacNaUhuTIXvyfkAq8l89IZ/kegFVyw/7KkJGRGqYdEZrf27Xsg==", + "dependencies": { + "@vue/reactivity": "3.4.32", + "@vue/runtime-core": "3.4.32", + "@vue/shared": "3.4.32", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/server-renderer/-/server-renderer-3.4.32.tgz", + "integrity": "sha512-3c4rd0522Ao8hKjzgmUAbcjv2mBnvnw0Ld2f8HOMCuWJZjYie/p8cpIoYJbeP0VV2JYmrJJMwGQDO5RH4iQ30A==", + "dependencies": { + "@vue/compiler-ssr": "3.4.32", + "@vue/shared": "3.4.32" + }, + "peerDependencies": { + "vue": "3.4.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/@vue/shared/-/shared-3.4.32.tgz", + "integrity": "sha512-ep4mF1IVnX/pYaNwxwOpJHyBtOMKWoKZMbnUyd+z0udqIxLUh7YCCd/JfDna8aUrmnG9SFORyIq2HzEATRrQsg==" + }, + "node_modules/@vue/tsconfig": { + "version": "0.5.1", + "resolved": "https://r.cnpmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://r.cnpmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://r2.cnpmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://r.cnpmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://r2.cnpmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://r.cnpmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://r2.cnpmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://r.cnpmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://r2.cnpmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://r.cnpmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://r.cnpmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://r2.cnpmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://r.cnpmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://r2.cnpmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://r2.cnpmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://r.cnpmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://r.cnpmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/marked": { + "version": "13.0.2", + "resolved": "https://r.cnpmjs.org/marked/-/marked-13.0.2.tgz", + "integrity": "sha512-J6CPjP8pS5sgrRqxVRvkCIkZ6MFdRIjDkwUwgJ9nL2fbmM6qGQeB2C16hi8Cc9BOzj6xXzy0jyi0iPIfnMHYzA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://r2.cnpmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://r.cnpmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://r.cnpmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://r.cnpmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://r.cnpmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-all2": { + "version": "6.2.2", + "resolved": "https://r.cnpmjs.org/npm-run-all2/-/npm-run-all2-6.2.2.tgz", + "integrity": "sha512-Q+alQAGIW7ZhKcxLt8GcSi3h3ryheD6xnmXahkMRVM5LYmajcUrSITm8h+OPC9RYWMV2GR0Q1ntTUCfxaNoOJw==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.3", + "memorystream": "^0.3.1", + "minimatch": "^9.0.0", + "pidtree": "^0.6.0", + "read-package-json-fast": "^3.0.2", + "shell-quote": "^1.7.3" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^14.18.0 || ^16.13.0 || >=18.0.0", + "npm": ">= 8" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://r.cnpmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://r2.cnpmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://r2.cnpmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://r.cnpmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://r.cnpmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://r.cnpmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://r.cnpmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/rollup": { + "version": "4.18.1", + "resolved": "https://r.cnpmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://r.cnpmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://r2.cnpmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://r2.cnpmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://r.cnpmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://r.cnpmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://r.cnpmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://r.cnpmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/vite": { + "version": "5.3.4", + "resolved": "https://r.cnpmjs.org/vite/-/vite-5.3.4.tgz", + "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://r.cnpmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/vue": { + "version": "3.4.32", + "resolved": "https://r.cnpmjs.org/vue/-/vue-3.4.32.tgz", + "integrity": "sha512-9mCGIAi/CAq7GtaLLLp2J92pEic+HArstG+pq6F+H7+/jB9a0Z7576n4Bh4k79/50L1cKMIhZC3MC0iGpl+1IA==", + "dependencies": { + "@vue/compiler-dom": "3.4.32", + "@vue/compiler-sfc": "3.4.32", + "@vue/runtime-dom": "3.4.32", + "@vue/server-renderer": "3.4.32", + "@vue/shared": "3.4.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://r.cnpmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "2.0.26", + "resolved": "https://r.cnpmjs.org/vue-tsc/-/vue-tsc-2.0.26.tgz", + "integrity": "sha512-tOhuwy2bIXbMhz82ef37qeiaQHMXKQkD6mOF6CCPl3/uYtST3l6fdNyfMxipudrQTxTfXVPlgJdMENBFfC1CfQ==", + "dev": true, + "dependencies": { + "@volar/typescript": "~2.4.0-alpha.15", + "@vue/language-core": "2.0.26", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://r2.cnpmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + } + } +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package.json new file mode 100644 index 0000000..80554ef --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/package.json @@ -0,0 +1,29 @@ +{ + "name": "aippt-vue", + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "@types/pako": "^2.0.3", + "base64-js": "^1.5.1", + "marked": "^13.0.2", + "pako": "^2.1.0", + "vue": "^3.4.29" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.2.0", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/public/favicon.png b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..f6415235f651a377d8eb82eba8c935d1e7e7a2e7 GIT binary patch literal 2725 zcmV;W3R?AvP)PxP|Fs`y@AJA3a&N;8!e|^~8C#Ub-a>(-rb-AP5(=c% z$V^P+5iHVxCeXADU>+?2K}BdBo+XhO5>d%eoR-o^F^r`xB4Gq2p-3dT&+|TK@3mID z_Bn}(kLjM-v-UZ2&i;Sv`+sY#?-PE@WvwkGEq$3478%QF0wc!S0DJ5oL_kF7j=g6k z3GlX3@}e>9@;tVQNaZ(`l3)GOS{t-l=_+gF3)b3xV=TsiwP20SMtUf+!s?d*loFI8 zyG1!r?)BMkrm(Wn_t_+pfje>?1E5~FBTDoRt?j5zEm|A2wixZ64+C)^+~4exnRg2d z$`?G(0Z=GUK)L!3fZ!?cmD-aAEG~$=eHg(J0Is;8pG{Nq-ZU{Ji6KoaNyn0=hAton z#<9_3qWAKwKvrDv0{5&CSJ4x!1Lg^V51}tazPyf>d4)n3L9h^)w#mlCjY$tg3dXg=wZc)H&0KZwKxF{@P$7ZBW*}77k}wboIVgrg6w01bBxkvH zWB_WlWVK1{dRNdDZ`L)LYjZ^0zUBJ)3c(U1K>->K-T!4FhdUtAq+&qU;zhWN;*>~Nxj}# zp0w>|H&a)K_x4yvTw_Zt5 z?neSI6Qg+UcEx)lluQo9o~0bYj657y5b^;lq+U&SwA=ckMom+#rc6&JOieiunp!QT zd6<6fgqQHdW7}BrsZp-_+()@!{s!K4>dBmT{@LXE`apSIRrU6R?sHe?f+Y|r29|*s zh6>Q1_jXFH(%IK)nv)#u)6*%F6DgC^DHW%KmZjrXKvvwc|Fyk5|Mb7H>$x?&@Z9UH zynZZZ2ebeo$?+|U3fZHysThXq{r?u3QMFcK2oms%z1G#hD9t!O4D zQ^qGXlQl!bEkO&$Z6sn*O7qRT9^tHc?_uq_i&=8smne+P;M^7GvE{a{{OqMSm~;9m zeB{c-D?F z6Si&o20Q=x1`hmulB+-Ubyj`#GYpj(=6-yBR~JY1!nGmnwPCp608~@ks5t(?ZW8;RgX-!3gj)kzKNUIZUy5ep& zeQhaoP8s2Xc^kQLtYi6g zf6C%NKb<%XvnAT>XzslATkP8Y0w0|FZf;n60YfwUxNE~MzPrCPB}I{;%T@6N`n`7KgYi3f6SBLzmbPGKg**Je4l%F zu4HJikHGUXqcT2GW$~G}vHF&axbzc$#P%&e;48O3MNo)Xuyg?@{{9?P5D^AGIp3Xz zWc2svy9blBn#Q&oP8}DcNmGk)Ir_W~5nd>;?!r$Z1md&Rx z&J!qwHSo@X36?FooxlF#VjkbRho8Q7kTX9v%G`ycs9XWx4+%m=9CnZ6QUv8#DCM#f z5ox!KZMUFawNxi8_?( z;pcB07pML#5x08cC4dF>#Nt$UI` zS#k#Ndf#k}j!=Z;JfBkDW1#5MS5lM;Lb0HTLI`}p&%C1~(&^ZJX~IdZhCR}TXP)^_ z9=z{yzWeNI_P+cUtFC&4Km6j^gtJOSVL;>sgyNx$LRS(b1xyZ`gm^k6BA`DE87}1* z?hhI2_bC?@aV!Ku*SI>vs)YTLrgn!;>_x5(&AMf3GU29G_fhKe`TXBr$hx&VIixfv zE5$0ceE}fAA4L?PD`mhxQ2f!#qEBw?ar$b5-GMI~* zS&TVhAmaGrA_n`sjQ$|(y5^&<72*Pj*1V}x`knWyRXR*fG&nTYU~H<*SfxcPpJ!aB z)M(Qt#dHtpi~-Mjc*Y~NKCucY2LS{59K+=tGY11^40LCIH2uA^X$m+gvkY46)yAmx zjs*w8ZA|s5rcyOb)lw!JnyFSoHA!e`jW!1BW^Ww;h3{mid3=Vpf z%R;`;qu=j_mfp2SL^d3;8#|gNLZ@wMHKATJ)M|#R+bJ8GdP~#lnCt{}`M|Y6 zS*Hm_&R4`aMIo;!m4$MjqL>vIauN8B{wy(N<@W%;wB@~QFk%ePnw0mt0!bS>PMFQE zHr(heTDxVt_B?e_t!n_?i=Dc2If(K?z9myV8cZPwZm zt=VA>qpnDr(gl*;HXGgNBykK#mjxHmvSb8dNLDb4A(!t0%7o{4XRcH>^TmgYA4x_> z%hIJJld{Ud7fecj>LOVx-H4WOWcJzxR&#izbd8T6beRa;W|MQDds)%L32viO|4%qQ z8p!y#Etg7MDwaiBbDGhNXl(=Syn@Szy~Lb3PnXbK4)MvBnHNanDc)8-FN$RG{4o)! f{+dDjzc2n5)W;Lq1{jA200000NkvXXu0mjfW)n#O literal 0 HcmV?d00001 diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/App.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/App.vue new file mode 100644 index 0000000..a5c71b9 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/App.vue @@ -0,0 +1,12 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/base.css b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/logo.svg b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/main.css b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/main.css new file mode 100644 index 0000000..3bbaf55 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/assets/main.css @@ -0,0 +1,5 @@ +@import './base.css'; + +#app { + margin: 0 auto; +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/AiPpt.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/AiPpt.vue new file mode 100644 index 0000000..35ec183 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/AiPpt.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GenerateOutline.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GenerateOutline.vue new file mode 100644 index 0000000..b7e55b8 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GenerateOutline.vue @@ -0,0 +1,211 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue new file mode 100644 index 0000000..953acce --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue @@ -0,0 +1,360 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue new file mode 100644 index 0000000..20f593c --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue @@ -0,0 +1,194 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue new file mode 100644 index 0000000..9e961fc --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts new file mode 100644 index 0000000..0ac3a5f --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js new file mode 100644 index 0000000..64fcd80 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js @@ -0,0 +1,2903 @@ +// 页面切场动画 +const transitionList = [ + { + name: "分割", + config: { + split: { + dir: "in", + }, + spd: "slow", + }, + key: "split", + }, + { + name: "切出", + config: { + cut: {}, + spd: "fast", + }, + key: "cut", + }, + { + name: "形状", + config: { + spd: "slow", + wedge: true, + }, + key: "wedge", + }, + { + name: "抽出", + config: { + pull: { + dir: "l", + }, + spd: "med", + }, + key: "pull", + }, + { + name: "推出", + config: { + spd: "slow", + push: { + dir: "u", + }, + }, + key: "push", + }, + { + name: "插入", + config: { + cover: { + dir: "d", + }, + spd: "slow", + }, + key: "cover", + }, + { + name: "擦除", + config: { + wipe: { + dir: "l", + }, + spd: "slow", + }, + key: "wipe", + }, + { + name: "新闻快报", + config: { + spd: "med", + newsflash: true, + }, + key: "newsflash", + }, + { + name: "梳理", + config: { + spd: "slow", + comb: { + dir: "horz", + }, + }, + key: "comb", + }, + { + name: "棋盘", + config: { + spd: "slow", + checker: { + dir: "horz", + }, + }, + key: "checker", + }, + { + name: "淡出", + config: { + fade: {}, + spd: "med", + }, + key: "fade", + }, + { + name: "溶解", + config: { + spd: "slow", + dissolve: true, + }, + key: "dissolve", + }, + { + name: "百叶窗", + config: { + blinds: { + dir: "horz", + }, + spd: "slow", + }, + key: "blinds", + }, + { + name: "线条", + config: { + spd: "slow", + randomBar: { + dir: "vert", + }, + }, + key: "randomBar", + }, + { + name: "轮幅", + config: { + spd: "slow", + wheel: { + spokes: 8, + }, + }, + key: "wheel", + }, + { + name: "随机", + config: { + random: true, + spd: "slow", + }, + key: "random", + }, +]; + +// 元素动画 +const animationList = [ + { + name: "退场动画", + children: [ + { + name: "消失", + children: [ + { + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 1, + presetSubtype: 0, + }, + ], + }, + { + name: "飞出", + children: [ + { + duration: 500, + name: "到顶部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 1, + }, + { + duration: 500, + name: "到右侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 2, + }, + { + duration: 500, + name: "到右上部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 3, + }, + { + duration: 500, + name: "到底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 4, + }, + { + duration: 500, + name: "到右下部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 6, + }, + { + duration: 500, + name: "到左侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 8, + }, + { + duration: 500, + name: "到左上部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 9, + }, + { + duration: 500, + name: "到左下部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 2, + presetSubtype: 12, + }, + ], + }, + { + name: "百叶窗", + children: [ + { + duration: 500, + name: "垂直", + startType: 1, + presetClass: "exit", + text: false, + presetId: 3, + presetSubtype: 5, + }, + { + duration: 500, + name: "水平", + startType: 1, + presetClass: "exit", + text: false, + presetId: 3, + presetSubtype: 10, + }, + ], + }, + { + name: "盒状", + children: [ + { + duration: 500, + name: "内", + startType: 1, + presetClass: "exit", + text: false, + presetId: 4, + presetSubtype: 16, + }, + { + duration: 500, + name: "外", + startType: 1, + presetClass: "exit", + text: false, + presetId: 4, + presetSubtype: 32, + }, + ], + }, + { + name: "棋盘", + children: [ + { + duration: 500, + name: "上", + startType: 1, + presetClass: "exit", + text: false, + presetId: 5, + presetSubtype: 5, + }, + { + duration: 500, + name: "跨越", + startType: 1, + presetClass: "exit", + text: false, + presetId: 5, + presetSubtype: 10, + }, + ], + }, + { + name: "圆形扩展", + children: [ + { + duration: 998, + name: "内", + startType: 1, + presetClass: "exit", + text: false, + presetId: 6, + presetSubtype: 16, + }, + { + duration: 998, + name: "外", + startType: 1, + presetClass: "exit", + text: false, + presetId: 6, + presetSubtype: 32, + }, + ], + }, + { + name: "缓慢移除", + children: [ + { + duration: 1000, + name: "到顶部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 7, + presetSubtype: 1, + }, + { + duration: 1000, + name: "到右侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 7, + presetSubtype: 2, + }, + { + duration: 1000, + name: "到底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 7, + presetSubtype: 4, + }, + { + duration: 1000, + name: "到左侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 7, + presetSubtype: 8, + }, + ], + }, + { + name: "菱形", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "exit", + text: false, + presetId: 8, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "exit", + text: false, + presetId: 8, + presetSubtype: 32, + }, + ], + }, + { + name: "向外溶解", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 9, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 10, + presetSubtype: 0, + }, + ], + }, + { + name: "闪烁一次", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 11, + presetSubtype: 0, + }, + ], + }, + { + name: "切出", + children: [ + { + duration: 500, + name: "到顶部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 12, + presetSubtype: 1, + }, + { + duration: 500, + name: "到右侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 12, + presetSubtype: 2, + }, + { + duration: 500, + name: "到底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 12, + presetSubtype: 4, + }, + { + duration: 500, + name: "到左侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 12, + presetSubtype: 8, + }, + ], + }, + { + name: "十字形扩展", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "exit", + text: false, + presetId: 13, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "exit", + text: false, + presetId: 13, + presetSubtype: 32, + }, + ], + }, + { + name: "随机线条", + children: [ + { + duration: 500, + name: "垂直", + startType: 1, + presetClass: "exit", + text: false, + presetId: 14, + presetSubtype: 5, + }, + { + duration: 500, + name: "水平", + startType: 1, + presetClass: "exit", + text: false, + presetId: 14, + presetSubtype: 10, + }, + ], + }, + { + name: "螺旋飞出", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 15, + presetSubtype: 0, + }, + ], + }, + { + name: "劈裂", + children: [ + { + duration: 500, + name: "左右向中央收缩", + startType: 1, + presetClass: "exit", + text: false, + presetId: 16, + presetSubtype: 21, + }, + { + duration: 500, + name: "上下向中央收缩", + startType: 1, + presetClass: "exit", + text: false, + presetId: 16, + presetSubtype: 26, + }, + { + duration: 500, + name: "中央向左右展开", + startType: 1, + presetClass: "exit", + text: false, + presetId: 16, + presetSubtype: 37, + }, + { + duration: 500, + name: "中央向上下展开", + startType: 1, + presetClass: "exit", + text: false, + presetId: 16, + presetSubtype: 42, + }, + ], + }, + { + name: "层叠", + children: [ + { + duration: 500, + name: "到顶部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 17, + presetSubtype: 1, + }, + { + duration: 500, + name: "到右侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 17, + presetSubtype: 2, + }, + { + duration: 500, + name: "到底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 17, + presetSubtype: 4, + }, + { + duration: 500, + name: "到左侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 17, + presetSubtype: 8, + }, + { + duration: 500, + name: "跨越", + startType: 1, + presetClass: "exit", + text: false, + presetId: 17, + presetSubtype: 10, + }, + ], + }, + { + name: "阶梯状", + children: [ + { + duration: 500, + name: "右上", + startType: 1, + presetClass: "exit", + text: false, + presetId: 18, + presetSubtype: 3, + }, + { + duration: 500, + name: "右下", + startType: 1, + presetClass: "exit", + text: false, + presetId: 18, + presetSubtype: 6, + }, + { + duration: 500, + name: "左上", + startType: 1, + presetClass: "exit", + text: false, + presetId: 18, + presetSubtype: 9, + }, + { + duration: 500, + name: "左下", + startType: 1, + presetClass: "exit", + text: false, + presetId: 18, + presetSubtype: 12, + }, + ], + }, + { + name: "旋转", + children: [ + { + duration: 999, + name: "垂直", + startType: 1, + presetClass: "exit", + text: false, + presetId: 19, + presetSubtype: 5, + }, + { + duration: 999, + name: "水平", + startType: 1, + presetClass: "exit", + text: false, + presetId: 19, + presetSubtype: 10, + }, + ], + }, + { + name: "扇形展开", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 20, + presetSubtype: 0, + }, + ], + }, + { + name: "轮子", + children: [ + { + duration: 1000, + name: "1轮幅图案", + startType: 1, + presetClass: "exit", + text: false, + presetId: 21, + presetSubtype: 1, + }, + { + duration: 1000, + name: "2轮幅图案", + startType: 1, + presetClass: "exit", + text: false, + presetId: 21, + presetSubtype: 2, + }, + { + duration: 1000, + name: "3轮幅图案", + startType: 1, + presetClass: "exit", + text: false, + presetId: 21, + presetSubtype: 3, + }, + { + duration: 1000, + name: "4轮幅图案", + startType: 1, + presetClass: "exit", + text: false, + presetId: 21, + presetSubtype: 4, + }, + { + duration: 1000, + name: "8轮幅图案", + startType: 1, + presetClass: "exit", + text: false, + presetId: 21, + presetSubtype: 8, + }, + ], + }, + { + name: "擦除", + children: [ + { + duration: 500, + name: "自顶部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 22, + presetSubtype: 1, + }, + { + duration: 500, + name: "自右侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 22, + presetSubtype: 2, + }, + { + duration: 500, + name: "自底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 22, + presetSubtype: 4, + }, + { + duration: 500, + name: "自左侧", + startType: 1, + presetClass: "exit", + text: false, + presetId: 22, + presetSubtype: 8, + }, + ], + }, + { + name: "缩放", + children: [ + { + duration: 500, + name: "内", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 16, + }, + { + duration: 500, + name: "放大到屏幕底部", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 20, + }, + { + duration: 500, + name: "外", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 32, + }, + { + duration: 500, + name: "轻微放大", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 272, + }, + { + duration: 500, + name: "轻微缩小", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 288, + }, + { + duration: 500, + name: "缩小到屏幕中心", + startType: 1, + presetClass: "exit", + text: false, + presetId: 23, + presetSubtype: 544, + }, + ], + }, + { + name: "随机效果", + children: [ + { + duration: 1, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 24, + presetSubtype: 0, + }, + ], + }, + { + name: "飞旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 25, + presetSubtype: 0, + }, + ], + }, + { + name: "弹跳", + children: [ + { + duration: 90, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 26, + presetSubtype: 0, + }, + ], + }, + { + name: "颜色打字机", + children: [ + { + name: "", + startType: 1, + presetClass: "exit", + text: true, + attr: { + dur: "50", + }, + presetId: 27, + presetSubtype: 0, + }, + ], + }, + { + name: "字幕式", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 28, + presetSubtype: 0, + }, + ], + }, + { + name: "渐出", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 29, + presetSubtype: 0, + }, + ], + }, + { + name: "浮动", + children: [ + { + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 30, + presetSubtype: 0, + }, + ], + }, + { + name: "光速", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 34, + presetSubtype: 0, + }, + ], + }, + { + name: "玩具风车", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 35, + presetSubtype: 0, + }, + ], + }, + { + name: "挥舞", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: true, + presetId: 38, + presetSubtype: 0, + }, + ], + }, + { + name: "线形", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 39, + presetSubtype: 0, + }, + ], + }, + { + name: "展开", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: true, + presetId: 40, + presetSubtype: 0, + }, + ], + }, + { + name: "挥鞭式", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: true, + presetId: 41, + presetSubtype: 0, + }, + ], + }, + { + name: "中心旋转", + children: [ + { + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 43, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变式回旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 45, + presetSubtype: 0, + }, + ], + }, + { + name: "上升", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 47, + presetSubtype: 0, + }, + ], + }, + { + name: "投掷", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 48, + presetSubtype: 0, + }, + ], + }, + { + name: "回旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 49, + presetSubtype: 0, + }, + ], + }, + { + name: "伸缩", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 50, + presetSubtype: 0, + }, + ], + }, + { + name: "放大", + children: [ + { + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 51, + presetSubtype: 0, + }, + ], + }, + { + name: "向下曲线", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 52, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变式缩放", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 53, + presetSubtype: 16, + }, + ], + }, + { + name: "滑翔", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 54, + presetSubtype: 0, + }, + ], + }, + { + name: "收缩", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 55, + presetSubtype: 0, + }, + ], + }, + { + name: "空翻", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: true, + presetId: 56, + presetSubtype: 0, + }, + ], + }, + { + name: "折叠", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "exit", + text: false, + presetId: 58, + presetSubtype: 0, + }, + ], + }, + ], + }, + { + name: "路径动画", + children: [ + { + name: "路径", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "path", + text: false, + attr: { + path: "M 0 0 L 0.25 0 E", + }, + presetId: 0, + presetSubtype: 0, + }, + ], + }, + ], + }, + { + name: "入场动画", + children: [ + { + name: "出现", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 1, + presetSubtype: 0, + }, + ], + }, + { + name: "飞入", + children: [ + { + duration: 1000, + name: "自顶部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 1, + }, + { + duration: 1000, + name: "自右侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 2, + }, + { + duration: 1000, + name: "自右上部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 3, + }, + { + duration: 1000, + name: "自底部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 4, + }, + { + duration: 1000, + name: "自右下部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 6, + }, + { + duration: 1000, + name: "自左侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 8, + }, + { + duration: 1000, + name: "自左上部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 9, + }, + { + duration: 1000, + name: "自左下部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 2, + presetSubtype: 12, + }, + ], + }, + { + name: "百叶窗", + children: [ + { + duration: 1000, + name: "垂直", + startType: 1, + presetClass: "entr", + text: false, + presetId: 3, + presetSubtype: 5, + }, + { + duration: 1000, + name: "水平", + startType: 1, + presetClass: "entr", + text: false, + presetId: 3, + presetSubtype: 10, + }, + ], + }, + { + name: "盒状", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "entr", + text: false, + presetId: 4, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "entr", + text: false, + presetId: 4, + presetSubtype: 32, + }, + ], + }, + { + name: "棋盘", + children: [ + { + duration: 1000, + name: "下", + startType: 1, + presetClass: "entr", + text: false, + presetId: 5, + presetSubtype: 5, + }, + { + duration: 1000, + name: "跨越", + startType: 1, + presetClass: "entr", + text: false, + presetId: 5, + presetSubtype: 10, + }, + ], + }, + { + name: "圆形扩展", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "entr", + text: false, + presetId: 6, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "entr", + text: false, + presetId: 6, + presetSubtype: 32, + }, + ], + }, + { + name: "缓慢进入", + children: [ + { + duration: 2000, + name: "自顶部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 7, + presetSubtype: 1, + }, + { + duration: 2000, + name: "自右侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 7, + presetSubtype: 2, + }, + { + duration: 2000, + name: "自底部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 7, + presetSubtype: 4, + }, + { + duration: 2000, + name: "自左侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 7, + presetSubtype: 8, + }, + ], + }, + { + name: "菱形", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "entr", + text: false, + presetId: 8, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "entr", + text: false, + presetId: 8, + presetSubtype: 32, + }, + ], + }, + { + name: "向内溶解", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 9, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 10, + presetSubtype: 0, + }, + ], + }, + { + name: "闪烁一次", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 11, + presetSubtype: 0, + }, + ], + }, + { + name: "切入", + children: [ + { + duration: 500, + name: "自顶部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 12, + presetSubtype: 1, + }, + { + duration: 500, + name: "自右侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 12, + presetSubtype: 2, + }, + { + duration: 500, + name: "自底部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 12, + presetSubtype: 4, + }, + { + duration: 500, + name: "自左侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 12, + presetSubtype: 8, + }, + ], + }, + { + name: "十字形扩展", + children: [ + { + duration: 1000, + name: "内", + startType: 1, + presetClass: "entr", + text: false, + presetId: 13, + presetSubtype: 16, + }, + { + duration: 1000, + name: "外", + startType: 1, + presetClass: "entr", + text: false, + presetId: 13, + presetSubtype: 32, + }, + ], + }, + { + name: "随机线条", + children: [ + { + duration: 1000, + name: "垂直", + startType: 1, + presetClass: "entr", + text: false, + presetId: 14, + presetSubtype: 5, + }, + { + duration: 1000, + name: "水平", + startType: 1, + presetClass: "entr", + text: false, + presetId: 14, + presetSubtype: 10, + }, + ], + }, + { + name: "螺旋飞入", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 15, + presetSubtype: 0, + }, + ], + }, + { + name: "劈裂", + children: [ + { + duration: 500, + name: "左右向中央收缩", + startType: 1, + presetClass: "entr", + text: false, + presetId: 16, + presetSubtype: 21, + }, + { + duration: 500, + name: "上下向中央收缩", + startType: 1, + presetClass: "entr", + text: false, + presetId: 16, + presetSubtype: 26, + }, + { + duration: 500, + name: "中央向左右展开", + startType: 1, + presetClass: "entr", + text: false, + presetId: 16, + presetSubtype: 37, + }, + { + duration: 500, + name: "中央向上下展开", + startType: 1, + presetClass: "entr", + text: false, + presetId: 16, + presetSubtype: 42, + }, + ], + }, + { + name: "伸展", + children: [ + { + duration: 500, + name: "自顶部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 17, + presetSubtype: 1, + }, + { + duration: 500, + name: "自右侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 17, + presetSubtype: 2, + }, + { + duration: 500, + name: "自底部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 17, + presetSubtype: 4, + }, + { + duration: 500, + name: "自左侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 17, + presetSubtype: 8, + }, + { + duration: 500, + name: "跨越", + startType: 1, + presetClass: "entr", + text: false, + presetId: 17, + presetSubtype: 10, + }, + ], + }, + { + name: "阶梯状", + children: [ + { + duration: 500, + name: "右上", + startType: 1, + presetClass: "entr", + text: false, + presetId: 18, + presetSubtype: 3, + }, + { + duration: 500, + name: "右下", + startType: 1, + presetClass: "entr", + text: false, + presetId: 18, + presetSubtype: 6, + }, + { + duration: 500, + name: "左上", + startType: 1, + presetClass: "entr", + text: false, + presetId: 18, + presetSubtype: 9, + }, + { + duration: 500, + name: "左下", + startType: 1, + presetClass: "entr", + text: false, + presetId: 18, + presetSubtype: 12, + }, + ], + }, + { + name: "旋转", + children: [ + { + duration: 2000, + name: "垂直", + startType: 1, + presetClass: "entr", + text: false, + presetId: 19, + presetSubtype: 5, + }, + { + duration: 2000, + name: "水平", + startType: 1, + presetClass: "entr", + text: false, + presetId: 19, + presetSubtype: 10, + }, + ], + }, + { + name: "扇形展开", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 20, + presetSubtype: 0, + }, + ], + }, + { + name: "轮子", + children: [ + { + duration: 1000, + name: "1轮幅图案", + startType: 1, + presetClass: "entr", + text: false, + presetId: 21, + presetSubtype: 1, + }, + { + duration: 1000, + name: "2轮幅图案", + startType: 1, + presetClass: "entr", + text: false, + presetId: 21, + presetSubtype: 2, + }, + { + duration: 1000, + name: "3轮幅图案", + startType: 1, + presetClass: "entr", + text: false, + presetId: 21, + presetSubtype: 3, + }, + { + duration: 1000, + name: "4轮幅图案", + startType: 1, + presetClass: "entr", + text: false, + presetId: 21, + presetSubtype: 4, + }, + { + duration: 1000, + name: "8轮幅图案", + startType: 1, + presetClass: "entr", + text: false, + presetId: 21, + presetSubtype: 8, + }, + ], + }, + { + name: "擦除", + children: [ + { + duration: 500, + name: "自顶部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 22, + presetSubtype: 1, + }, + { + duration: 500, + name: "自右侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 22, + presetSubtype: 2, + }, + { + duration: 500, + name: "自底部", + startType: 1, + presetClass: "entr", + text: false, + presetId: 22, + presetSubtype: 4, + }, + { + duration: 500, + name: "自左侧", + startType: 1, + presetClass: "entr", + text: false, + presetId: 22, + presetSubtype: 8, + }, + ], + }, + { + name: "缩放", + children: [ + { + duration: 500, + name: "内", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 16, + }, + { + duration: 500, + name: "外", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 32, + }, + { + duration: 500, + name: "从屏幕底部缩小", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 36, + }, + { + duration: 500, + name: "轻微放大", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 272, + }, + { + duration: 500, + name: "轻微缩小", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 288, + }, + { + duration: 500, + name: "从屏幕中心放大", + startType: 1, + presetClass: "entr", + text: false, + presetId: 23, + presetSubtype: 528, + }, + ], + }, + { + name: "随机效果", + children: [ + { + duration: 1, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 24, + presetSubtype: 0, + }, + ], + }, + { + name: "飞旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 25, + presetSubtype: 0, + }, + ], + }, + { + name: "弹跳", + children: [ + { + duration: 290, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 26, + presetSubtype: 0, + }, + ], + }, + { + name: "颜色打字机", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: true, + attr: { + dur: "50", + }, + presetId: 27, + presetSubtype: 0, + }, + ], + }, + { + name: "字幕式", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 28, + presetSubtype: 0, + }, + ], + }, + { + name: "渐入", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 29, + presetSubtype: 0, + }, + ], + }, + { + name: "浮动", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 30, + presetSubtype: 0, + }, + ], + }, + { + name: "旋转式由远及近", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 31, + presetSubtype: 0, + }, + ], + }, + { + name: "光速", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 34, + presetSubtype: 0, + }, + ], + }, + { + name: "玩具风车", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 35, + presetSubtype: 0, + }, + ], + }, + { + name: "升起", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 37, + presetSubtype: 0, + }, + ], + }, + { + name: "挥舞", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: true, + presetId: 38, + presetSubtype: 0, + }, + ], + }, + { + name: "线形", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 39, + presetSubtype: 0, + }, + ], + }, + { + name: "展开", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: true, + presetId: 40, + presetSubtype: 0, + }, + ], + }, + { + name: "挥鞭式", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: true, + presetId: 41, + presetSubtype: 0, + }, + ], + }, + { + name: "上升", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 42, + presetSubtype: 0, + }, + ], + }, + { + name: "中心旋转", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 43, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变式回旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 45, + presetSubtype: 0, + }, + ], + }, + { + name: "下降", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 47, + presetSubtype: 0, + }, + ], + }, + { + name: "投掷", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 48, + presetSubtype: 0, + }, + ], + }, + { + name: "回旋", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 49, + presetSubtype: 0, + }, + ], + }, + { + name: "压缩", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 50, + presetSubtype: 0, + }, + ], + }, + { + name: "放大", + children: [ + { + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 51, + presetSubtype: 0, + }, + ], + }, + { + name: "曲线向上", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 52, + presetSubtype: 0, + }, + ], + }, + { + name: "渐变式缩放", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 53, + presetSubtype: 16, + }, + ], + }, + { + name: "滑翔", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 54, + presetSubtype: 0, + }, + ], + }, + { + name: "展开", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 55, + presetSubtype: 0, + }, + ], + }, + { + name: "空翻", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: true, + presetId: 56, + presetSubtype: 0, + }, + ], + }, + { + name: "折叠", + children: [ + { + duration: 1000, + name: "", + startType: 1, + presetClass: "entr", + text: false, + presetId: 58, + presetSubtype: 0, + }, + ], + }, + ], + }, + { + name: "强调动画", + children: [ + { + name: "更改填充颜色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + attr: { + scheme: "accent2", + }, + presetId: 1, + presetSubtype: 2, + }, + ], + }, + { + name: "更改字体", + children: [ + { + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + font: "黑体", + }, + presetId: 2, + presetSubtype: 0, + }, + ], + }, + { + name: "更改字体颜色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + scheme: "accent2", + }, + presetId: 3, + presetSubtype: 2, + }, + ], + }, + { + name: "更改字号", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + fontSize: "1.5", + }, + presetId: 4, + presetSubtype: 2, + }, + ], + }, + { + name: "更改字形", + children: [ + { + duration: 2000, + name: "无", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 0, + }, + { + duration: 2000, + name: "加粗", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 1, + }, + { + duration: 2000, + name: "斜体", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 2, + }, + { + duration: 2000, + name: "加粗斜体", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 3, + }, + { + duration: 2000, + name: "下划线", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 4, + }, + { + duration: 2000, + name: "加粗下划线", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 5, + }, + { + duration: 2000, + name: "斜体下划线", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 6, + }, + { + duration: 2000, + name: "加粗斜体下划线", + startType: 1, + presetClass: "emph", + text: true, + presetId: 5, + presetSubtype: 7, + }, + ], + }, + { + name: "放大缩小", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 6, + presetSubtype: 0, + }, + ], + }, + { + name: "更改线条颜色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + attr: { + scheme: "accent2", + }, + presetId: 7, + presetSubtype: 2, + }, + ], + }, + { + name: "陀螺旋", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 8, + presetSubtype: 0, + }, + ], + }, + { + name: "透明", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 9, + presetSubtype: 0, + }, + ], + }, + { + name: "加粗闪烁", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + presetId: 10, + presetSubtype: 0, + }, + ], + }, + { + name: "爆炸", + children: [ + { + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 14, + presetSubtype: 0, + }, + ], + }, + { + name: "加粗展示", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + presetId: 15, + presetSubtype: 0, + }, + ], + }, + { + name: "着色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + scheme: "accent2", + }, + presetId: 16, + presetSubtype: 0, + }, + ], + }, + { + name: "添加下划线", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + presetId: 18, + presetSubtype: 0, + }, + ], + }, + { + name: "混色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + attr: { + scheme: "accent2", + }, + presetId: 19, + presetSubtype: 0, + }, + ], + }, + { + name: "彩色波纹", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + scheme: "accent2", + }, + presetId: 20, + presetSubtype: 0, + }, + ], + }, + { + name: "补色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 21, + presetSubtype: 0, + }, + ], + }, + { + name: "补色2", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 22, + presetSubtype: 0, + }, + ], + }, + { + name: "对比色", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 23, + presetSubtype: 0, + }, + ], + }, + { + name: "加深", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 24, + presetSubtype: 0, + }, + ], + }, + { + name: "不饱和", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 25, + presetSubtype: 0, + }, + ], + }, + { + name: "忽明忽暗", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 26, + presetSubtype: 0, + }, + ], + }, + { + name: "闪动", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 27, + presetSubtype: 0, + }, + ], + }, + { + name: "颜色延伸", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + scheme: "accent2", + }, + presetId: 28, + presetSubtype: 0, + }, + ], + }, + { + name: "变淡", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 30, + presetSubtype: 0, + }, + ], + }, + { + name: "样式强调", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + attr: { + scheme: "accent2", + }, + presetId: 31, + presetSubtype: 0, + }, + ], + }, + { + name: "跷跷板", + children: [ + { + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 32, + presetSubtype: 0, + }, + ], + }, + { + name: "垂直突出显示", + children: [ + { + duration: 1500, + name: "", + startType: 1, + presetClass: "emph", + text: false, + attr: { + scheme: "accent2", + }, + presetId: 33, + presetSubtype: 0, + }, + ], + }, + { + name: "波浪线", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + presetId: 34, + presetSubtype: 0, + }, + ], + }, + { + name: "闪烁", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: false, + presetId: 35, + presetSubtype: 0, + }, + ], + }, + { + name: "闪现", + children: [ + { + duration: 2000, + name: "", + startType: 1, + presetClass: "emph", + text: true, + presetId: 36, + presetSubtype: 0, + }, + ], + }, + ], + }, +] + +export { transitionList, animationList } diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js new file mode 100644 index 0000000..8a52ade --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js @@ -0,0 +1,834 @@ +async function drawChart(chart, anchor, canvas, ctx) { + if (!canvas) { + canvas = document.createElement('canvas') + let width = anchor[2] + let height = anchor[3] + canvas.width = width * 2 + canvas.height = height * 2 + canvas.style.width = width + 'px' + canvas.style.height = height + 'px' + let ctx = canvas.getContext('2d') + ctx.scale(2, 2) + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = 'high' + } + if (!ctx) { + ctx = canvas.getContext('2d') + } + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = 'high' + let title = chart.title + let legend = chart.legend + let chartData = chart.chartData[0] + let chartType = chartData.chartType + if (chartType == 'bar') { + // 柱状图、条形图 + let type = chartData.extInfo.type + if (type == 'bar') { + // 条形图 + await drawBarChartWithBar(title, chartData, legend, anchor, canvas, ctx) + } else { + // 柱状图 + await drawBarChartWithCol(title, chartData, legend, anchor, canvas, ctx) + } + } else if (chartType == 'pie' || chartType == 'doughnut') { + // 饼图、圆环图 + await drawPieChart(title, chartData, legend, anchor, canvas, ctx) + } else if (chartType == 'line') { + // 折线图 + await drawLineChart(title, chartData, legend, anchor, canvas, ctx) + } else { + // 其他: 暂不支持 + await drawRect(ctx, { + strokeStyle: { + lineWidth: 0.5, + paint: { type: 'color', color: { color: -2500135 } } + }, + anchor: [anchor[0] + 0.5, anchor[1] + 0.5, anchor[2] - 1, anchor[3] - 1] + }) + let str = '该图表暂不支持渲染' + ctx.font = `${Math.min(anchor[2] * 0.056, 16)}px 等线` + ctx.fillStyle = 'rgb(153, 153, 153)' + let textWidth = ctx.measureText(str).width + ctx.fillText(str, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] / 2 - 8) + } + return canvas +} + +async function drawBarChartWithBar(title, chartData, legend, anchor, canvas, ctx) { + if (title) { + ctx.font = `${Math.min(anchor[3] * 0.064, 18.5)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + let textWidth = ctx.measureText(title).width + ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) + } + let extInfo = chartData.extInfo + let series = chartData.series + let categoryAxis = chartData.categoryAxis + let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null + let minValue = 0, maxValue = 0 + for (let i = 0; i < series.length; i++) { + minValue = Math.min(minValue, ...series[i].value.data) + maxValue = Math.max(maxValue, ...series[i].value.data) + } + ctx.lineWidth = 0.5 + ctx.font = `${Math.min(anchor[2] * 0.048, 14)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.strokeStyle = 'rgb(217, 217, 217)' + let categorys = series[0].category.data + let maxCw = ctx.measureText('00').width + for (let i = 0; i < categorys.length; i++) { + let w = ctx.measureText(categorys[i] + '0').width + if (w > maxCw) { + maxCw = w + } + } + let sGap = valueAxes && !valueAxes.deleted ? maxCw : anchor[2] * 0.15 + let x = anchor[0] + sGap + let xWidth = anchor[2] - sGap - anchor[2] * 0.04 + let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 + let y = anchor[1] + startY + let yHeight = anchor[3] - startY - anchor[3] * 0.15 + let minTicks = xWidth / 10 > 20 ? 11 : 6 + let ticks = calculateTicks(minValue, maxValue, minTicks, 11) + let xGap = xWidth / (ticks.length - 1) + ctx.beginPath() + for (let i = 0; i < ticks.length; i++) { + // x轴数值 + if (valueAxes && !valueAxes.deleted) { + ctx.textAlign = 'center' + let v = ticks[i] + let vs = v.toString() + if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { + vs = v.toFixed(1) + } + ctx.fillText(vs, x, y + yHeight + anchor[3] * 0.05) + ctx.textAlign = 'start' + } + if (extInfo.majorGridlines == 'true') { + // 网格线 + ctx.moveTo(x, y) + ctx.lineTo(x, y + yHeight) + } + x += xGap + } + ctx.stroke() + let yGap = anchor[3] * 0.04 // y开始 + y += yGap + x = anchor[0] + sGap + let vGap = anchor[3] * 0.015 // 柱子间距 + let catGap = vGap * 5 // 类目间距 + let categoryHeight = (yHeight - catGap * (categorys.length - 1) - yGap * 2) / categorys.length + let vHeight = (categoryHeight - vGap * (series.length - 1)) / series.length + // 绘制类目和柱状图 + for (let i = 0; i < categorys.length; i++) { + if (categoryAxis && !categoryAxis.deleted) { + ctx.fillStyle = 'rgb(89, 89, 89)' + let _cy = (categoryHeight + catGap) * i + categoryHeight / 2 + 6 + ctx.textAlign = 'right' + ctx.fillText(categorys[categorys.length - 1 - i], x - 4, y + _cy) + ctx.textAlign = 'start' + } + for (let j = 0; j < series.length; j++) { + let seriesData = series[series.length - 1 - j] + let valueData = seriesData.value.data + let vWidth = (valueData[valueData.length - 1 - i] / ticks[ticks.length - 1]) * xWidth + let _x = x + let _y = y + (categoryHeight + catGap) * i + (vHeight + vGap) * j + let _anchor = [_x, _y, vWidth, vHeight] + // 柱状图 + await drawRect(ctx, { + fillStyle: seriesData.property.fillStyle, + strokeStyle: seriesData.property.strokeStyle, + anchor: _anchor + }) + } + } + if (legend) { + // 绘制v标签标识 + x = anchor[0] + sGap + let vTexts = [] + let vTextWidth = 0 + for (let i = 0; i < series.length; i++) { + let s = series[i].text.data[0] + vTexts.push(s) + vTextWidth += ctx.measureText(s).width + } + vGap = anchor[3] * 0.03 + let _iw = Math.min(anchor[2] * 0.028, 15) + let _y = y + yHeight + anchor[3] * 0.1 + let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 + for (let i = 0; i < vTexts.length; i++) { + await drawRect(ctx, { + fillStyle: series[series.length - 1 - i].property.fillStyle, + strokeStyle: series[series.length - 1 - i].property.strokeStyle, + anchor: [_x, _y - _iw, _iw, _iw] + }) + _x += (_iw * 1.25) + ctx.fillStyle = 'rgb(89, 89, 89)' + let str = vTexts[vTexts.length - 1 - i] + ctx.fillText(str, _x, _y) + _x += ctx.measureText(str).width + _x += vGap + } + } +} + +async function drawBarChartWithCol(title, chartData, legend, anchor, canvas, ctx) { + if (title) { + ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + let textWidth = ctx.measureText(title).width + ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) + } + let extInfo = chartData.extInfo + let series = chartData.series + let categoryAxis = chartData.categoryAxis + let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null + let minValue = 0, maxValue = 0 + for (let i = 0; i < series.length; i++) { + minValue = Math.min(minValue, ...series[i].value.data) + maxValue = Math.max(maxValue, ...series[i].value.data) + } + ctx.lineWidth = 0.5 + ctx.font = `${Math.min(anchor[3] * 0.06, 14)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.strokeStyle = 'rgb(217, 217, 217)' + let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 + let y = anchor[1] + startY + let yHeight = anchor[3] - startY - anchor[3] * 0.15 + let mixTicks = yHeight / 10 > 20 ? 11 : 6 + let ticks = calculateTicks(minValue, maxValue, mixTicks, 11) + let xGap = ctx.measureText(ticks[ticks.length - 1] + '00').width + let x = anchor[0] + xGap + let xWidth = anchor[2] - xGap * 1.5 + let yGap = yHeight / (ticks.length - 1) + ctx.beginPath() + for (let i = 0; i < ticks.length; i++) { + if (valueAxes && !valueAxes.deleted) { + // y轴数值 + ctx.textAlign = 'right' + let v = ticks[ticks.length - 1 - i] + let vs = v.toString() + if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { + vs = v.toFixed(1) + } + ctx.fillText(vs, x - 4, y + 6) + ctx.textAlign = 'start' + } + if (extInfo.majorGridlines == 'true') { + // 网格线 + ctx.moveTo(x, y) + ctx.lineTo(x + xWidth, y) + } + y += yGap + } + ctx.stroke() + x += xGap + y -= yGap + let vGap = anchor[2] * 0.01 // 柱子间距 + let catGap = vGap * 6 // 类目间距 + let categorys = series[0].category.data + let categoryWidth = (xWidth - catGap * (categorys.length - 1) - xGap * 1.5) / categorys.length + let vWidth = (categoryWidth - vGap * (series.length - 1)) / series.length + // 绘制类目和柱状图 + for (let i = 0; i < categorys.length; i++) { + if (categoryAxis && !categoryAxis.deleted) { + let _cx = (categoryWidth + catGap) * i + categoryWidth / 2 - ctx.measureText(categorys[i]).width / 2 + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.fillText(categorys[i], x + _cx, y + anchor[3] * 0.055) + } + for (let j = 0; j < series.length; j++) { + let vHeight = (series[j].value.data[i] / ticks[ticks.length - 1]) * yHeight + let _x = x + (categoryWidth + catGap) * i + (vWidth + vGap) * j + let _y = y - vHeight + let _anchor = [_x, _y, vWidth, vHeight] + // 柱状图 + await drawRect(ctx, { + fillStyle: series[j].property.fillStyle, + strokeStyle: series[j].property.strokeStyle, + anchor: _anchor + }) + } + } + if (legend) { + // 绘制v标签标识 + x = anchor[0] + xGap + let vTexts = [] + let vTextWidth = 0 + for (let i = 0; i < series.length; i++) { + let s = series[i].text.data[0] + vTexts.push(s) + vTextWidth += ctx.measureText(s).width + } + vGap = anchor[2] * 0.02 + let _iw = Math.min(anchor[2] * 0.025, 15) + let _y = y + anchor[3] * 0.125 + let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 + for (let i = 0; i < vTexts.length; i++) { + await drawRect(ctx, { + fillStyle: series[i].property.fillStyle, + strokeStyle: series[i].property.strokeStyle, + anchor: [_x, _y - _iw, _iw, _iw] + }) + _x += (_iw * 1.25) + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.fillText(vTexts[i], _x, _y) + _x += ctx.measureText(vTexts[i]).width + _x += vGap + } + } +} + +async function drawPieChart(title, chartData, legend, anchor, canvas, ctx) { + if (title == '') { + title = chartData.series[0].text.data[0] + } + if (title) { + ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + let textWidth = ctx.measureText(title).width + ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) + } + let extInfo = chartData.extInfo + let holeSize = +(extInfo.holeSize || 0) / 100 + let series = chartData.series + let values = series[0].value.data + let dataPoints = series[0].dataPoint + let totalValue = 0 + for (let i = 0; i < values.length; i++) { + totalValue += (+values[i]) + } + let xGap = anchor[2] * 0.05 // 开始间距 + let x = anchor[0] + xGap + let xWidth = anchor[2] - xGap * 2 + let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 + let y = anchor[1] + startY + let yHeight = anchor[3] - startY - anchor[3] * 0.15 + let centerX = xWidth / 2 + let centerY = yHeight / 2 + let radius = Math.min(centerX, centerY) + ctx.lineWidth = 0.5 + ctx.font = `${Math.min(anchor[2] * 0.048, 14)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.save() + ctx.translate(x + centerX, y + centerY) + // arc 是以3点钟方向开始,反向旋转-90调整到0点开始 + ctx.rotate(-90 * Math.PI / 180) + ctx.translate(-x - centerX, -y - centerY) + let startAngle = 0 + if (extInfo.startAngle) { + startAngle = extInfo.startAngle * (Math.PI / 180) + } + for (let i = 0; i < values.length; i++) { + let property = dataPoints[i].property + ctx.fillStyle = await toCtxPaint(ctx, property.fillStyle, property.anchor || anchor) + if (property.strokeStyle) { + ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 + let lineCap = property.strokeStyle.lineCap + if (!lineCap || lineCap == 'FLAT') { + lineCap = 'butt' + } + ctx.lineCap = lineCap.toLowerCase() + ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor || anchor) + } + let sliceAngle = (2 * Math.PI * values[i]) / totalValue + ctx.beginPath() + ctx.moveTo(x + centerX, y + centerY) + // 实心圆 + ctx.arc(x + centerX, y + centerY, radius, startAngle, startAngle + sliceAngle, false) + if (holeSize > 0) { + // 空心圆 + let holeRadius = radius * holeSize + ctx.arc(x + centerX, y + centerY, holeRadius, startAngle + sliceAngle, startAngle, true) + ctx.closePath() + ctx.save() + ctx.clip() + ctx.fill() + ctx.stroke() + ctx.restore() + } else { + ctx.closePath() + ctx.fill() + ctx.stroke() + } + startAngle += sliceAngle + } + ctx.restore() + if (legend) { + // 绘制类目标签标识 + let vTexts = [] + let vTextWidth = 0 + let categorys = series[0].category.data + for (let i = 0; i < categorys.length; i++) { + let s = categorys[i] + vTexts.push(s) + vTextWidth += ctx.measureText(s).width + } + let vGap = anchor[2] * 0.03 + let _iw = Math.min(anchor[2] * 0.028, 15) + let _y = y + yHeight + anchor[3] * 0.125 + let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 + for (let i = 0; i < vTexts.length; i++) { + let property = dataPoints[i].property + await drawRect(ctx, { + fillStyle: property.fillStyle, + strokeStyle: property.strokeStyle, + anchor: [_x, _y - _iw, _iw, _iw] + }) + _x += (_iw * 1.25) + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.fillText(vTexts[i], _x, _y) + _x += ctx.measureText(vTexts[i]).width + _x += vGap + } + } +} + +async function drawLineChart(title, chartData, legend, anchor, canvas, ctx) { + if (title) { + ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + let textWidth = ctx.measureText(title).width + ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) + } + let extInfo = chartData.extInfo + let smooth = extInfo.smooth == 'true' + let series = chartData.series + let categoryAxis = chartData.categoryAxis + let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null + let minValue = 0, maxValue = 0 + for (let i = 0; i < series.length; i++) { + minValue = Math.min(minValue, ...series[i].value.data) + maxValue = Math.max(maxValue, ...series[i].value.data) + } + ctx.lineWidth = 0.5 + ctx.font = `${Math.min(anchor[3] * 0.06, 14)}px 等线` + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.strokeStyle = 'rgb(217, 217, 217)' + let ticks = calculateTicks(minValue, maxValue, 5, 10) + let xGap = ctx.measureText(ticks[ticks.length - 1] + '00').width + let x = anchor[0] + xGap + let xWidth = anchor[2] - xGap * 1.5 + let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 + let y = anchor[1] + startY + let yHeight = anchor[3] - startY - anchor[3] * 0.15 + let yGap = yHeight / (ticks.length - 1) + ctx.beginPath() + for (let i = 0; i < ticks.length; i++) { + // y轴数值 + if (valueAxes && !valueAxes.deleted) { + ctx.textAlign = 'right' + let v = ticks[ticks.length - 1 - i] + let vs = v.toString() + if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { + vs = v.toFixed(1) + } + ctx.fillText(vs, x - 4, y + 6) + ctx.textAlign = 'start' + } + if (extInfo.majorGridlines == 'true') { + // 网格线 + ctx.moveTo(x, y) + ctx.lineTo(x + xWidth, y) + } + y += yGap + } + ctx.stroke() + x += xGap + y -= yGap + let catGap = anchor[2] * 0.05 // 类目间距 + let categorys = series[0].category.data + let categoryWidth = (xWidth - catGap * (categorys.length - 1) - xGap * 1.5) / categorys.length + let cxList = [] + // 绘制类目 + for (let i = 0; i < categorys.length; i++) { + let _cx = (categoryWidth + catGap) * i + categoryWidth / 2 - ctx.measureText(categorys[i]).width / 2 + cxList.push(_cx) + if (categoryAxis && !categoryAxis.deleted) { + ctx.textAlign = 'center' + ctx.fillText(categorys[i], x + _cx, y + anchor[3] * 0.05) + ctx.textAlign = 'start' + } + } + // 绘制折线 + for (let i = 0; i < series.length; i++) { + let property = series[i].property + if (property.strokeStyle) { + ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 + let lineCap = property.strokeStyle.lineCap + if (!lineCap || lineCap == 'FLAT') { + lineCap = 'butt' + } + ctx.lineCap = lineCap.toLowerCase() + ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) + } + ctx.beginPath() + let points = [] + for (let j = 0; j < categorys.length; j++) { + let vHeight = (series[i].value.data[j] / ticks[ticks.length - 1]) * yHeight + let _x = x + cxList[j] + let _y = y - vHeight + if (j == 0) { + ctx.moveTo(_x, _y) + } else if (smooth) { + points.push({ x: _x, y: _y }) + } else { + ctx.lineTo(_x, _y) + } + } + if (smooth) { + let j = 0 + for (; j < points.length - 2; j++) { + let xc = (points[j].x + points[j + 1].x) / 2 + let yc = (points[j].y + points[j + 1].y) / 2 + ctx.quadraticCurveTo(points[j].x, points[j].y, xc, yc) + } + ctx.quadraticCurveTo(points[j].x, points[j].y, points[j + 1].x, points[j + 1].y) + } + ctx.stroke() + } + if (legend) { + // 绘制v标签标识 + x = anchor[0] + xGap + let vTexts = [] + let vTextWidth = 0 + for (let i = 0; i < series.length; i++) { + let s = series[i].text.data[0] + vTexts.push(s) + vTextWidth += ctx.measureText(s).width + } + let vGap = anchor[2] * 0.02 + let _iw = anchor[2] * 0.04 + let _y = y + anchor[3] * 0.128 + let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw + 2) * vTexts.length) / 2 + for (let i = 0; i < vTexts.length; i++) { + let property = series[i].property + if (property.strokeStyle) { + ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 + let lineCap = property.strokeStyle.lineCap + if (!lineCap || lineCap == 'FLAT') { + lineCap = 'butt' + } + ctx.lineCap = lineCap.toLowerCase() + ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) + } + ctx.beginPath() + ctx.moveTo(_x, _y - 4) + ctx.lineTo(_x + _iw, _y - 4) + ctx.stroke() + _x += (_iw + 2) + ctx.fillStyle = 'rgb(89, 89, 89)' + ctx.fillText(vTexts[i], _x, _y) + _x += ctx.measureText(vTexts[i]).width + _x += vGap + } + } +} + +function calculateTicks(minValue, maxValue, minTicks, maxTicks) { + let range = maxValue - minValue + let rawInterval = range / (minTicks - 1) + let magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval))) + let normalizedInterval = rawInterval / magnitude + let adjustedInterval + if (normalizedInterval <= 1.5) { + adjustedInterval = 1 + } else if (normalizedInterval <= 3) { + adjustedInterval = 2 + } else if (normalizedInterval <= 7) { + adjustedInterval = 5 + } else { + adjustedInterval = 10 + } + adjustedInterval *= magnitude + let tickEnd = Math.ceil(maxValue / adjustedInterval) * adjustedInterval + let ticks = [] + for (let tick = 0; tick <= tickEnd; tick += adjustedInterval) { + ticks.push(tick) + } + if (ticks.length < minTicks) { + for (let i = ticks.length; i < minTicks; i++) { + ticks.push(i * adjustedInterval) + } + } else { + while (ticks.length > maxTicks) { + adjustedInterval *= 2 + ticks = [] + tickEnd = Math.ceil(maxValue / adjustedInterval) * adjustedInterval + for (let tick = 0; tick <= tickEnd; tick += adjustedInterval) { + ticks.push(tick) + } + } + } + return ticks +} + +async function drawRect(ctx, property) { + ctx.fillStyle = await toCtxPaint(ctx, property.fillStyle, property.anchor) + if (property.strokeStyle) { + ctx.lineWidth = property.strokeStyle.lineWidth || 1 + ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) + } + ctx.fillRect(property.anchor[0], property.anchor[1], property.anchor[2], property.anchor[3]) +} + +function toCtxPaint(ctx, paint, anchor, isBackground, defaultColor) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + return new Promise((resolve, reject) => { + if (!paint) { + resolve(defaultColor || 'transparent') + } else if (paint.type == 'noFill') { + // 无填充 + resolve('transparent') + } else if (paint.type == 'color') { + // 颜色 + resolve(toColor(paint.color, defaultColor)) + } else if (paint.type == 'bgFill') { + // 背景填充 + resolve(ctx.bgFillStyle || defaultColor || 'transparent') + } else if (paint.type == 'groupFill') { + // 组合背景 + let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle + if (groupFillStyle) { + toCtxPaint(ctx, groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { + resolve(res) + }) + } else { + resolve(defaultColor || 'transparent') + } + } else if (paint.type == 'gradient') { + // 渐变 + let gradient = paint.gradient + let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] + let centerX = x + width / 2 + let centerY = y + height / 2 + let gradientObj + // linear,circular,rectangular,shape + if (gradient.gradientType == 'circular') { + // 射线 + let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) + let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 + let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 + gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) + } else { + // 线性 + let startX = x + let startY = centerY + let endX = x + width + let endY = centerY + if (gradient.angle) { + let radians = gradient.angle * Math.PI / 180 + let midX = (startX + endX) / 2 + let midY = (startY + endY) / 2 + let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) + let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) + let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) + let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) + startX = newStartX + startY = newStartY + endX = newEndX + endY = newEndY + } + gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) + } + for (let i = 0; i < gradient.colors.length; i++) { + let color = gradient.colors[i] + gradientObj.addColorStop(gradient.fractions[i], toColor(color)) + } + resolve(gradientObj) + } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { + resolve('transparent') + } else if (paint.type == 'texture') { + // 图片或纹理 + let texture = paint.texture + loadChartImage(texture.imageData).then(img => { + let pat = createCtxTexturePattern(ctx, img, texture, anchor) + resolve(pat) + }) + } else if (paint.type == 'pattern') { + // 图案 + let pattern = paint.pattern + // let prst = pattern.prst + let fgColor = pattern.fgColor.realColor + let bgColor = pattern.bgColor.realColor + let width = anchor[2], height = anchor[3] + let imgCanvas = document.createElement('canvas') + imgCanvas.width = width + imgCanvas.height = height + let imgCtx = imgCanvas.getContext('2d') + imgCtx.imageSmoothingEnabled = true + imgCtx.imageSmoothingQuality = 'high' + let imgData = imgCtx.createImageData(width, height) + let line = 0 + for (let i = 0; i < imgData.data.length; i += 4) { + if (++line % 16 == 0) { + // 前景 + imgData.data[i + 0] = (fgColor >> 16) & 255 + imgData.data[i + 1] = (fgColor >> 8) & 255 + imgData.data[i + 2] = (fgColor >> 0) & 255 + imgData.data[i + 3] = (fgColor >> 24) & 255 + } else { + // 背景 + imgData.data[i + 0] = (bgColor >> 16) & 255 + imgData.data[i + 1] = (bgColor >> 8) & 255 + imgData.data[i + 2] = (bgColor >> 0) & 255 + imgData.data[i + 3] = (bgColor >> 24) & 255 + } + if (i % 400 == 0) { + line += 2 + } + } + imgCtx.putImageData(imgData, 0, 0) + let imgSrc = imgCanvas.toDataURL() + let image = new Image() + image.src = imgSrc + image.onload = async function() { + resolve(ctx.createPattern(image, 'no-repeat')) + } + } + }) +} + +function createCtxTexturePattern(ctx, img, texture, anchor) { + let width = anchor[2] + let height = anchor[3] + let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' + if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { + return ctx.createPattern(img, mode) + } + if (texture.alignment || !texture.stretch) { + width = img.width + height = img.height + } + let patternCanvas = document.createElement('canvas') + patternCanvas.width = Math.max(1, width) + patternCanvas.height = Math.max(1, height) + let patternCtx = patternCanvas.getContext('2d') + patternCtx.imageSmoothingEnabled = true + patternCtx.imageSmoothingQuality = 'high' + if (texture.alpha >= 0 && texture.alpha < 100000) { + patternCtx.globalAlpha = texture.alpha / 100000 + } + let imgInsets = null + if (texture.insets) { + let top = texture.insets[0] / 100000 + let left = texture.insets[1] / 100000 + let bottom = texture.insets[2] / 100000 + let right = texture.insets[3] / 100000 + let x = img.width * left + let y = img.height * top + let w = img.width * (1 - left - right) + let h = img.height * (1 - top - bottom) + imgInsets = [x, y, w, h] + } + if (texture.stretch) { + let top = texture.stretch[0] / 100000 + let left = texture.stretch[1] / 100000 + let bottom = texture.stretch[2] / 100000 + let right = texture.stretch[3] / 100000 + let x = width * left + let y = height * top + let w = width * (1 - left - right) + let h = height * (1 - top - bottom) + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) + } else { + patternCtx.drawImage(img, x, y, w, h) + } + } else if (texture.alignment) { + let x = 0, y = 0 + if (texture.alignment == 'CENTER') { + if (width > anchor[2]) { + x = (width - anchor[2]) / 2 + } + if (height > anchor[3]) { + y = (height - anchor[3]) / 2 + } + } + patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) + } else { + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) + } else { + patternCtx.drawImage(img, 0, 0, width, height) + } + } + if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { + // 重新着色 + let color = texture.duoTone[0].realColor + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) + let data = imageData.data + for(var i = 0; i < data.length; i += 4) { + let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 + // black / white + let prst = texture.duoTonePrst == 'white' ? 255 : 0 + data[i] = gray * r + (1 - gray) * prst + data[i + 1] = gray * g + (1 - gray) * prst + data[i + 2] = gray * b + (1 - gray) * prst + } + patternCtx.putImageData(imageData, 0, 0) + } + return ctx.createPattern(patternCanvas, mode) +} + +function toColor(colorObj, defaultColor) { + if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { + return defaultColor || 'transparent' + } + let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let a = ((color >> 24) & 255) / 255 + if (colorObj.realColor == null) { + if (colorObj.alpha != null && colorObj.alpha != -1) { + if (colorObj.alpha > 1000) { + a = colorObj.alpha / 100000 + } else { + a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 + } + a = Math.min(1, Math.max(0, a)) + } + if (colorObj.lumMod && colorObj.lumMod > 0) { + let value = colorObj.lumMod / 100000 + r = r * value + g = g * value + b = b * value + } + if (colorObj.lumOff && colorObj.lumOff > 0) { + let value = colorObj.lumOff / 100000 + r += 255 * value + g += 255 * value + b += 255 * value + } + } + return `rgba(${r}, ${g}, ${b}, ${a})` +} + +function loadChartImage(src) { + return new Promise(resolve => { + if (!src) { + resolve() + return + } + let img = new Image() + let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) + if (!eqOrigin) { + img.crossOrigin = 'anonymous' + } + img.src = src + img.onload = function() { + resolve(img) + } + img.onerror = function (e) { + resolve() + console.log('图片加载失败: ', src, e) + } + }) +} + +export { drawChart } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js new file mode 100644 index 0000000..05ea6d0 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js @@ -0,0 +1,95 @@ +import { Ppt2Canvas } from './ppt2canvas.js' + +async function drawPptxFun(pptxObj, idx) { + let canvas = document.createElement('canvas') + let width = pptxObj.width + let height = pptxObj.height + canvas.width = width * 2 + canvas.height = height * 2 + canvas.style.width = width + 'px' + canvas.style.height = height + 'px' + let ctx = canvas.getContext('2d') + ctx.scale(2, 2) + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = 'high' + let ppt2Canvas = new Ppt2Canvas(canvas, 'anonymous') + await ppt2Canvas.drawPptx(pptxObj, idx) + return ppt2Canvas.getCanvas() +} + +// drawPptxFun = async (pptxObj, idx) => return canvas +async function drawCover(pptxObj, drawPptxFun, grayScale) { + let pages = pptxObj.pages + if (pages.length == 1) { + let _canvas = await drawPptxFun(pptxObj, 0, pptxObj.width, pptxObj.height) + return _canvas.toDataURL() + } + async function drawPptxImage(pptxObj, idx) { + let _canvas = await drawPptxFun(pptxObj, idx) + let imgSrc = _canvas.toDataURL() + return new Promise(resolve => { + let image = new Image() + image.src = imgSrc + image.onload = async function() { + resolve(image) + } + }) + } + // let width = 1200, height = 676 + let width = 600, height = 338 + let canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + let ctx = canvas.getContext('2d') + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = 'high' + + ctx.fillStyle = 'rgb(212, 212, 212)' + ctx.fillRect(0, 0, width, height) + + let size = 0 + let w = width / 3.3, h = height / 3.3 + for (let i = 1; i < pages.length; i++) { + size++ + let x = 0 + let y = 0 + if (size == 2 || size == 7) { + x = w + (width - w * 3) / 2 + } else if (size == 3 || size == 5 || size == 8) { + x = width - w + } + if (size == 4 || size == 5) { + y = h + (height - h * 3) / 2 + } else if (size > 5) { + y = height - h + } + let image = await drawPptxImage(pptxObj, i) + ctx.drawImage(image, x, y, w, h) + if (size == 8) { + break + } + } + w = width * 0.65 + h = height * 0.65 + let image = await drawPptxImage(pptxObj, 0) + ctx.drawImage(image, (width - w) / 2, (height - h) / 2, w, h) + ctx.rect((width - w) / 2, (height - h) / 2, w, h) + ctx.lineWidth = 1 + ctx.strokeStyle = 'rgb(212, 212, 212)' + ctx.stroke() + if (grayScale) { + // 灰度 + let imageData = ctx.getImageData(0, 0, width, height) + let data = imageData.data + for (let i = 0; i < data.length; i += 4) { + let luminance = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114 + data[i] = luminance + data[i + 1] = luminance + data[i + 2] = luminance + } + ctx.putImageData(imageData, 0, 0) + } + return canvas.toDataURL() +} + +export { drawPptxFun, drawCover } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js new file mode 100644 index 0000000..08abc73 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js @@ -0,0 +1,692 @@ +// 创建空白页 +function createPage(page, width, height) { + return { + page: page || 1, + extInfo: { + background: { + realType: 'Background', + anchor: [0, 0, width || 960, height || 540], + fillStyle: { + type: 'color', + color: { + color: -1, + realColor: -1 + } + } + }, + slideMasterIdx: 0, + slideLayoutIdx: 0 + }, + children: [] + } +} + +// 创建文本框 +// @param subType 类型 => title1 标题; title2 副标题; content 正文内容 +// @param fontFamily 字体(默认 null) +// @param fontColor 文字颜色(默认 null) +function createTextBox(subType, fontFamily, fontColor) { + const fontSize = (subType == 'title1' ? 70 : (subType == 'title2' ? 35 : 18)) + const text = (subType == 'title1' || subType == 'title2' ? '输入标题' : '请输入内容') + const textWordWrap = (subType == 'title1' || subType == 'title2' ? false : true) + const textAlign = (subType == 'title1' || subType == 'title2' ? 'CENTER' : 'LEFT') + const width = (text.length + 1) * fontSize + const anchor = [(960 - width) / 2, 540 / 2 - fontSize, width, fontSize] + if (textAlign == 'CENTER') { + anchor[0] = (960 - width) / 2 + } else { + anchor[0] = 960 / 2 - width + } + const id = 'txt' + Math.floor((Math.random() * 100000) + 100000) + if (!fontColor && subType == 'title1') { + // 标题默认颜色 + fontColor = { + type: 'gradient', + gradient: { + angle: 90, + colors: [ + {color: -7614, realColor: -7614, alpha: 100000}, + {color: -1838, realColor: -1838, alpha: 100000}, + {color: -7614, realColor: -7614, alpha: 100000}, + {color: -25569, realColor: -25569, alpha: 100000}, + {color: -7614, realColor: -7614, alpha: 100000} + ], + fractions: [0.06, 0.26, 0.5, 0.71, 0.89], + gradientType: 'linear' + } + } + } else if (!fontColor) { + // 正文默认颜色 + fontColor = { + type: 'color', + color: { + scheme: null, + realColor: -16777216, + color: -16777216 + }, + gradient: null + } + } + return { + id: `${id}`, + type: 'text', + depth: 1, + point: [...anchor], + extInfo: { + property: { + realType: 'TextBox', + shapeType: 'rect', + anchor: [...anchor], + fillStyle: { + type: 'noFill' + }, + geometry: { + name: 'rect' + }, + textAutofit: 'SHAPE', + textDirection: 'HORIZONTAL', + textVerticalAlignment: 'TOP', + textWordWrap: textWordWrap, + textInsets: [3.6,7.2,3.6,7.2] + } + }, + children: [ + { + id: `${id}_p`, + pid: `${id}`, + type: 'p', + depth: 2, + extInfo: { + property: { + textAlign: textAlign, + leftMargin: 0 + } + }, + children: [ + { + id: `${id}_p_r`, + pid: `${id}_p`, + type: 'r', + text: text, + depth: 3, + extInfo: { + property: { + fontSize: fontSize, + bold: null, + fontFamily: fontFamily, + fontColor: {...fontColor}, + line: null, + lang: 'zh-CN' + } + } + } + ] + } + ] + } +} + +// 创建形状 +// @param geometryName 形状名称 => geometryMap key +// @param fillStyle 填充 +// @param strokeStylePaint 画笔填充 +function createGeometry(geometryName, fillStyle, strokeStylePaint) { + const width = 200 + const height = 200 + const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] + const id = 'txt' + Math.floor((Math.random() * 100000) + 100000) + if (!fillStyle) { + fillStyle = { + type: 'color', + color: { + scheme: null, + color: -10773547, + realColor: -10773547 + } + } + } + if (!strokeStylePaint) { + strokeStylePaint = { + type: 'color', + color: { + scheme: null, + color: -10773547, + realColor: -14532775, + shade: 15000 + } + } + } + return { + id: `${id}`, + type: 'text', + depth: 1, + point: [...anchor], + extInfo: { + property: { + realType: 'Auto', + shapeType: geometryName, + anchor: [...anchor], + fillStyle: {...fillStyle}, + strokeStyle: { + paint: {...strokeStylePaint}, + lineWidth: 1, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + geometry: { + name: geometryName, + data: null, + avLst: null + }, + textAutofit: 'NORMAL', + textDirection: 'HORIZONTAL', + textVerticalAlignment: 'MIDDLE', + textInsets: [3.6, 7.2, 3.6, 7.2] + } + }, + children: [ + { + id: `${id}_p`, + pid: `${id}`, + type: 'p', + depth: 2, + extInfo: { + property: { + textAlign: 'CENTER', + leftMargin: 0 + } + }, + children: [] + } + ] + } +} + +// 创建图片 +// @param src 图片src (url/base64) +function createImage(src, width, height) { + if (!width) { + width = 200 + } + if (!height) { + height = 200 + } + const extension = src.indexOf('.png') > -1 || src.indexOf('image/png') ? '.png' : '.jpg' + const id = 'img' + Math.floor((Math.random() * 100000) + 100000) + const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] + const contentType = extension == '.png' ? 'image/png' : 'image/jpeg' + return { + id: id, + depth: 1, + type: 'image', + point: [...anchor], + extInfo: { + property: { + image: src, + anchor: [...anchor], + extension: extension, + fileName: 'image' + extension, + contentType: contentType, + fillStyle: { + type: 'texture', + texture: { + imageData: '$image', + flipMode: 'NONE', + insets: [0, 0, 0, 0], + stretch: [0, 0, 0, 0], + contentType: contentType + } + }, + flipHorizontal: false, + flipVertical: false, + realType: 'Picture', + geometry: { + name: 'rect' + } + } + }, + children: [] + } +} + +// 创建表格 +// @param rowColumnDataList 表格数据: [['第1行1列', '第1行2列', '第1行3列'], ['第2行1列', '第2行2列', '第2行3列'], ['第3行1列', '第3行2列', '第3行3列']] +// @param rowFillStyles 填充色(按行循环交替) +// @param borderColor 边框颜色 +// @param fontColor 字体颜色 +function createTable(rowColumnDataList, rowFillStyles, borderColor, fontColor) { + const rowNum = rowColumnDataList.length + const columnNum = rowColumnDataList[0].length + const lineWidth = 1 + const fontSize = 16 + const textAlign = 'LEFT' + const rowHeight = 65, colWidth = 80 + const width = rowHeight * rowNum + lineWidth * (rowNum + 1) + const height = colWidth * columnNum + lineWidth * (columnNum + 1) + const tableAnchor = [(960 - width) / 2, (540 - height) / 2, width, height] + const id = 'tab' + Math.floor((Math.random() * 100000) + 100000) + const rows = [] + if (!rowFillStyles) { + rowFillStyles = [ + { + type: 'color', + color: { + color: -7555288, + realColor: -1378864, + lumMod: 20000, + lumOff: 80000 + } + }, + { + type: 'color', + color: { + color: -7555288, + realColor: -2823519, + lumMod: 40000, + lumOff: 60000 + } + } + ] + } + if (!fontColor) { + fontColor = { + type: 'color', + color: { + color: -16777216, + realColor: -16777216, + alpha: 100000 + } + } + } + if (borderColor == null) { + borderColor = -7555288 + } + for (let i = 0; i < rowNum; i++) { + const columns = [] + const fillStyle = rowFillStyles[i % rowFillStyles.length] + for (let j = 0; j < columnNum; j++) { + let text = rowColumnDataList[i][j] + columns.push({ + id: `${id}_r${i}_c${j}`, + pid: `${id}_r${i}`, + type: 'tableColumn', + depth: 3, + extInfo: { + property: { + realType: 'TableCell', + anchor: [tableAnchor[0] + colWidth * j + lineWidth * (j + 1), tableAnchor[1] + rowHeight * i + lineWidth * (i + 1), colWidth, rowHeight], + fillStyle: {...fillStyle}, + strokeStyle: {}, + geometry: { + name: 'tableColumn' + }, + textAutofit: 'NORMAL', + textDirection: 'HORIZONTAL', + textVerticalAlignment: 'MIDDLE', + textInsets: [3.6, 7.2, 3.6, 7.2], + columnWidth: colWidth, + borders: [ + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + }, + { + color: borderColor, + lineWidth: lineWidth, + lineCap: 'FLAT', + lineDash: 'SOLID', + lineCompound: 'SINGLE' + } + ] + } + }, + children: [ + { + id: `${id}_r${i}_c${j}_p`, + pid: `${id}_r${i}_c${j}`, + type: 'p', + depth: 4, + extInfo: { + property: { + textAlign: textAlign, + leftMargin: 0 + } + }, + children: [ + { + id: `${id}_r${i}_c${j}_p_r`, + pid: `${id}_r${i}_c${j}_p`, + type: 'r', + text: text, + depth: 5, + extInfo: { + property: { + fontSize: fontSize, + fontColor: {...fontColor}, + lang: 'zh-CN' + } + } + } + ] + } + ] + }) + } + rows.push({ + id: `${id}_r${i}`, + pid: `${id}`, + type: 'tableRow', + depth: 2, + extInfo: { + property: { + rowHeight: rowHeight + } + }, + children: columns + }) + } + return { + id: `${id}`, + pid: null, + type: 'table', + text: null, + depth: 1, + point: [...tableAnchor], + extInfo: { + property: { + anchor: [...tableAnchor], + realType: 'table', + numberOfRows: rowNum, + numberOfColumns: columnNum + } + }, + children: rows + } +} + +// 创建图表 +// @param title 图表标题 +// @param chartType 图表类型 pie/doughnut/bar/line +// @param rowColumnDataList 表格数据: +// 柱状图、折线图: [[' ','系列 1','系列 2','系列 3'], ['类别 1','4.3','2.4','2'], ['类别 2','2.5','4.4','2'], ['类别 3','3.5','1.8','3'], ['类别 4','4.5','2.8','5']] +// 饼图、环形图: [[' ','销售额'], ['第一季度','8.2'], ['第二季度','3.2'], ['第三季度','1.4'], ['第四季度','1.2']] +// @param colors 颜色 [{type:'color',color:{realColor:-1213135}}] +function createChart(title, chartType, rowColumnDataList, colors) { + if (!colors) { + colors = [ + {type: 'color', color: { color: -478429, realColor: -478429 }}, + {type: 'color', color: { color: -10130855, realColor: -10130855 }}, + {type: 'color', color: { color: -12143947, realColor: -12143947 }}, + {type: 'color', color: { color: -7558530, realColor: -7558530 }}, + {type: 'color', color: { color: -2920600, realColor: -2920600 }}, + {type: 'color', color: { color: -8232330, realColor: -8232330 }} + ] + } + if (chartType == 'pie' || chartType == 'doughnut') { + rowColumnDataList[0][1] = rowColumnDataList[0][1] || title + return createPieChart(rowColumnDataList, chartType == 'doughnut' ? 50 : 0, colors) + } else if (chartType == 'bar' || chartType == 'line') { + return createBarLineChart(title, chartType, rowColumnDataList, colors) + } + return null +} + +function createPieChart(rowColumnDataList, holeSize, colors) { + const width = 400 + const height = 220 + const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] + const id = 'chart' + Math.floor((Math.random() * 100000) + 100000) + const dataPoint = [] + for (let i = 1; i < rowColumnDataList.length; i++) { + dataPoint.push({ + property: { + anchor: null, + fillStyle: colors[(i - 1) % colors.length], + strokeStyle: { + paint: { + type: 'color', + color: { + scheme: 'lt1', + realColor: -1, + color: -1 + } + }, + lineWidth: 1.5 + }, + geometry: null, + shadow: null + } + }) + } + const chartData = { + chartType: holeSize ? 'doughnut' : 'pie', + series: [ + { + text: { + formula: 'Sheet1!$B$1', + formatCode: null, + data: [rowColumnDataList[0][1]] + }, + category: { + formula: 'Sheet1!$A$2:$A$' + rowColumnDataList.length, + formatCode: null, + data: rowColumnDataList.map(s => s[0]).splice(1) + }, + value: { + formula: 'Sheet1!$B$2:$B$' + rowColumnDataList.length, + formatCode: 'General', + data: rowColumnDataList.map(s => s[1]).splice(1) + }, + dataPoint: dataPoint, + property: null + } + ], + categoryAxis: null, + valueAxes: null, + extInfo: holeSize ? { holeSize: holeSize } : {} + } + return { + id: id, + type: 'graphicFrame', + depth: 1, + point: [...anchor], + extInfo: { + property: { + anchor: [...anchor], + chart: { + title: '', + legend: { + position: 'BOTTOM', + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + }, + excelData: [ + { + sheetName: 'Sheet1', + rows: rowColumnDataList + } + ], + chartData: [chartData] + }, + realType: 'graphicFrame' + } + }, + children: [] + } +} + +function createBarLineChart(title, chartType, rowColumnDataList, colors) { + const width = 460 + const height = 270 + const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] + const id = 'chart' + Math.floor((Math.random() * 100000) + 100000) + const series = [] + for (let i = 1; i < rowColumnDataList[0].length; i++) { + const vf = String.fromCharCode(65 + i) + series.push({ + text: { + formula: 'Sheet1!$' + vf + '$1', + formatCode: null, + data: [rowColumnDataList[0][i]] + }, + category: { + formula: 'Sheet1!$A$' + (i + 1) + ':$A$' + rowColumnDataList.length, + formatCode: null, + data: rowColumnDataList.map(s => s[0]).splice(1) + }, + value: { + formula: 'Sheet1!$' + vf + '$' + (i + 1) + ':$' + vf + '$' + rowColumnDataList.length, + formatCode: 'General', + data: rowColumnDataList.map(s => s[i]).splice(1) + }, + dataPoint: [null], + property: { + anchor: null, + fillStyle: chartType == 'line' ? null : colors[(i - 1) % colors.length], + strokeStyle: chartType == 'line' ? { + paint: colors[(i - 1) % colors.length], + lineWidth: 2.25, + lineCap: 'ROUND' + } : { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + }) + } + let extInfo = {} + if (chartType == 'bar') { + extInfo = { + type: 'col', + overlap: '-27', + gapWidth: '219', + majorGridlines: 'true' + } + } else if (chartType == 'line') { + extInfo = { majorGridlines: 'true' } + } + return { + id: id, + type: 'graphicFrame', + depth: 1, + point: [...anchor], + extInfo: { + property: { + anchor: [...anchor], + chart: { + title: title, + legend: { + position: 'BOTTOM', + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + }, + excelData: [ + { + sheetName: 'Sheet1', + rows: rowColumnDataList + } + ], + chartData: [ + { + chartType: chartType, + series: series, + categoryAxis: { + position: 'BOTTOM', + deleted: false, + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'color', + color: { + realColor: -2500135, + color: -16777216, + lumMod: 15000, + lumOff: 85000 + } + }, + lineWidth: 0.75, + lineCap: 'FLAT', + lineCompound: 'SINGLE' + }, + geometry: null, + shadow: null + } + }, + valueAxes: [ + { + position: 'LEFT', + deleted: false, + property: { + anchor: null, + fillStyle: { + type: 'noFill' + }, + strokeStyle: { + paint: { + type: 'noFill' + } + }, + geometry: null, + shadow: null + } + } + ], + extInfo: extInfo + } + ] + }, + realType: 'graphicFrame' + } + }, + children: [] + } +} + +export { createPage, createTextBox, createGeometry, createImage, createTable, createChart } diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js new file mode 100644 index 0000000..1d67490 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js @@ -0,0 +1,500 @@ +/* eslint-disable no-fallthrough */ +/* eslint-disable no-case-declarations */ +const geometryMap = {"curvedDownArrow":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 100000","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","wR:+- wd2 0 q1","q7:*/ wR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idy:*/ q11 h q7","maxAdj3:*/ 100000 idy ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss adj3 100000","x3:+- wR th 0","q2:*/ h h 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dx:*/ q5 wR h","x5:+- wR dx 0","x7:+- x3 dx 0","q6:+- aw 0 th","dh:*/ q6 1 2","x4:+- x5 0 dh","x8:+- x7 dh 0","aw2:*/ aw 1 2","x6:+- r 0 aw2","y1:+- b 0 ah","swAng:at2 ah dx","mswAng:+- 0 0 swAng","iy:+- b 0 idy","ix:+/ wR x3 2","q12:*/ th 1 2","dang2:at2 idy q12","stAng:+- 3cd4 swAng 0","stAng2:+- 3cd4 0 dang2","swAng2:+- dang2 0 cd4","swAng3:+- cd4 dang2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x6 b L x4 y1 L x5 y1 A wR h stAng mswAng L x3 t A wR h 3cd4 swAng L x8 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L l b A wR h cd2 swAng3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L l b A wR h cd2 cd4 L x3 t A wR h 3cd4 swAng L x8 y1 L x6 b L x4 y1 L x5 y1 A wR h stAng mswAng","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"quadArrowCallout":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:+- 50000 0 a2","a3:pin 0 adj3 maxAdj3","q2:*/ a3 2 1","maxAdj4:+- 100000 0 q2","a4:pin a1 adj4 maxAdj4","dx2:*/ ss a2 100000","dx3:*/ ss a1 200000","ah:*/ ss a3 100000","dx1:*/ w a4 200000","dy1:*/ h a4 200000","x8:+- r 0 ah","x2:+- hc 0 dx1","x7:+- hc dx1 0","x3:+- hc 0 dx2","x6:+- hc dx2 0","x4:+- hc 0 dx3","x5:+- hc dx3 0","y8:+- b 0 ah","y2:+- vc 0 dy1","y7:+- vc dy1 0","y3:+- vc 0 dx2","y6:+- vc dx2 0","y4:+- vc 0 dx3","y5:+- vc dx3 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L ah y3 L ah y4 L x2 y4 L x2 y2 L x4 y2 L x4 ah L x3 ah L hc t L x6 ah L x5 ah L x5 y2 L x7 y2 L x7 y4 L x8 y4 L x8 y3 L r vc L x8 y6 L x8 y5 L x7 y5 L x7 y7 L x5 y7 L x5 y8 L x6 y8 L hc b L x3 y8 L x4 y8 L x4 y7 L x2 y7 L x2 y5 L ah y5 L ah y6 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18515","adj2:val 18515","adj3:val 18515","adj4:val 48123"]},"funnel":{"guides":["d:*/ ss 1 20","rw2:+- wd2 0 d","rh2:+- hd4 0 d","t1:cos wd2 480000","t2:sin hd4 480000","da:at2 t1 t2","2da:*/ da 2 1","stAng1:+- cd2 0 da","swAng1:+- cd2 2da 0","swAng3:+- cd2 0 2da","rw3:*/ wd2 1 4","rh3:*/ hd4 1 4","ct1:cos hd4 stAng1","st1:sin wd2 stAng1","m1:mod ct1 st1 0","n1:*/ wd2 hd4 m1","dx1:cos n1 stAng1","dy1:sin n1 stAng1","x1:+- hc dx1 0","y1:+- hd4 dy1 0","ct3:cos rh3 da","st3:sin rw3 da","m3:mod ct3 st3 0","n3:*/ rw3 rh3 m3","dx3:cos n3 da","dy3:sin n3 da","x3:+- hc dx3 0","vc3:+- b 0 rh3","y2:+- vc3 dy3 0","x2:+- wd2 0 rw2","cd:*/ cd2 2 1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd4 stAng1 swAng1 L x3 y2 A rw3 rh3 da swAng3 Z M x2 hd4 A rw2 rh2 cd2 -21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"doubleWave":{"guides":["a1:pin 0 adj1 12500","a2:pin -10000 adj2 10000","y1:*/ h a1 100000","dy2:*/ y1 10 3","y2:+- y1 0 dy2","y3:+- y1 dy2 0","y4:+- b 0 y1","y5:+- y4 0 dy2","y6:+- y4 dy2 0","dx1:*/ w a2 100000","of2:*/ w a2 50000","x1:abs dx1","dx2:?: of2 0 of2","x2:+- l 0 dx2","dx8:?: of2 of2 0","x8:+- r 0 dx8","dx3:+/ dx2 x8 6","x3:+- x2 dx3 0","dx4:+/ dx2 x8 3","x4:+- x2 dx4 0","x5:+/ x2 x8 2","x6:+- x5 dx3 0","x7:+/ x6 x8 2","x9:+- l dx8 0","x15:+- r dx2 0","x10:+- x9 dx3 0","x11:+- x9 dx4 0","x12:+/ x9 x15 2","x13:+- x12 dx3 0","x14:+/ x13 x15 2","x16:+- r 0 x1","xAdj:+- hc dx1 0","il:max x2 x9","ir:min x8 x15","it:*/ h a1 50000","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 y1 C x3 y2 x4 y3 x5 y1 C x6 y2 x7 y3 x8 y1 L x15 y4 C x14 y6 x13 y5 x12 y4 C x11 y6 x10 y5 x9 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 6250","adj2:val 0"]},"parallelogram":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 200000","x2:*/ ss a 100000","x6:+- r 0 x1","x5:+- r 0 x2","x3:*/ x5 1 2","x4:+- r 0 x3","il:*/ wd2 a maxAdj","q1:*/ 5 a maxAdj","q2:+/ 1 q1 12","il:*/ q2 w 1","it:*/ q2 h 1","ir:+- r 0 il","ib:+- b 0 it","q3:*/ h hc x2","y1:pin 0 q3 h","y2:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L r t L x5 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"rightArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss w","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","dx3:*/ ss a3 100000","x3:+- r 0 dx3","x2:*/ w a4 100000","x1:*/ x2 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x2 t L x2 y2 L x3 y2 L x3 y1 L r vc L x3 y4 L x3 y3 L x2 y3 L x2 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"actionButtonForwardNext":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g12 vc L g11 g9 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g12 vc L g11 g9 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g12 vc L g11 g10 L g11 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartDisplay":{"guides":["x2:*/ w 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 0 3 L 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"plaqueTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t A dx dx 0 cd4 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 A dx dx 3cd4 cd4 L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r t L r dx A dx dx cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 b A dx dx cd2 cd4 L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonInformation":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g11:+- hc 0 dx2","g13:*/ ss 3 4","g14:*/ g13 1 32","g17:*/ g13 5 16","g18:*/ g13 3 8","g19:*/ g13 13 32","g20:*/ g13 19 32","g22:*/ g13 11 16","g23:*/ g13 13 16","g24:*/ g13 7 8","g25:+- g9 g14 0","g28:+- g9 g17 0","g29:+- g9 g18 0","g30:+- g9 g23 0","g31:+- g9 g24 0","g32:+- g11 g17 0","g34:+- g11 g19 0","g35:+- g11 g20 0","g37:+- g11 g22 0","g38:*/ g13 3 32"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M hc g9 A dx2 dx2 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M hc g9 A dx2 dx2 3cd4 21600000 Z M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g32 g29 L g34 g29 L g34 g30 L g32 g30 L g32 g31 L g37 g31 L g37 g30 L g35 g30 L g35 g28 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g35 g28 L g35 g30 L g37 g30 L g37 g31 L g32 g31 L g32 g30 L g34 g30 L g34 g29 L g32 g29 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc g9 A dx2 dx2 3cd4 21600000 Z M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g35 g28 L g35 g30 L g37 g30 L g37 g31 L g32 g31 L g32 g30 L g34 g30 L g34 g29 L g32 g29 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartOfflineStorage":{"guides":["x4:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":false,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":5,"path":"M 2 4 L 3 4","stroked":true,"w":5,"windingRule":1},{"extrusionOk":true,"fill":"NONE","filled":false,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"upArrow":{"guides":["maxAdj2:*/ 100000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dy2:*/ ss a2 100000","y2:+- t dy2 0","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:*/ x1 dy2 wd2","y1:+- y2 0 dy1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L hc t L r y2 L x2 y2 L x2 b L x1 b L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"chartStar":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 0 0 L 10 10 M 0 10 L 10 0 M 5 0 L 5 10","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"actionButtonBlank":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"corner":{"guides":["maxAdj1:*/ 100000 h ss","maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 maxAdj1","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","dy1:*/ ss a1 100000","y1:+- b 0 dy1","cx1:*/ x1 1 2","cy1:+/ y1 b 2","d:+- w 0 h","it:?: d y1 t","ir:?: d r x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L x1 y1 L r y1 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"cloudCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","ht:cat2 hd2 dxPos dyPos","wt:sat2 wd2 dxPos dyPos","g2:cat2 wd2 ht wt","g3:sat2 hd2 ht wt","g4:+- hc g2 0","g5:+- vc g3 0","g6:+- g4 0 xPos","g7:+- g5 0 yPos","g8:mod g6 g7 0","g9:*/ ss 6600 21600","g10:+- g8 0 g9","g11:*/ g10 1 3","g12:*/ ss 1800 21600","g13:+- g11 g12 0","g14:*/ g13 g6 g8","g15:*/ g13 g7 g8","g16:+- g14 xPos 0","g17:+- g15 yPos 0","g18:*/ ss 4800 21600","g19:*/ g11 2 1","g20:+- g18 g19 0","g21:*/ g20 g6 g8","g22:*/ g20 g7 g8","g23:+- g21 xPos 0","g24:+- g22 yPos 0","g25:*/ ss 1200 21600","g26:*/ ss 600 21600","x23:+- xPos g26 0","x24:+- g16 g25 0","x25:+- g23 g12 0","il:*/ w 2977 21600","it:*/ h 3262 21600","ir:*/ w 17087 21600","ib:*/ h 17337 21600","g27:*/ w 67 21600","g28:*/ h 21577 21600","g29:*/ w 21582 21600","g30:*/ h 1235 21600","pang:at2 dxPos dyPos"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":43200,"path":"M 3900 14370 A 6753 9190 -11429249 7426832 A 5333 7267 -8646143 5396714 A 4365 5945 -8748475 5983381 A 4857 6595 -7859164 7034504 A 5333 7273 -4722533 6541615 A 6775 9220 -2776035 7816140 A 5785 7867 37501 6842000 A 6752 9215 1347096 6910353 A 7720 10543 3974558 4542661 A 4360 5918 -16496525 8804134 A 4345 5945 -14809710 9151131 Z","stroked":true,"w":43200,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x23 yPos A g26 g26 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x24 g17 A g25 g25 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x25 g24 A g12 g12 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":43200,"path":"M 4693 26177 A 4345 5945 5204520 1585770 M 6928 34899 A 4360 5918 4416628 686848 M 16478 39090 A 6752 9215 8257449 844866 M 28827 34751 A 6752 9215 387196 959901 M 34129 22954 A 5785 7867 -4217541 4255042 M 41798 15354 A 5333 7273 1819082 1665090 M 38324 5426 A 4857 6595 -824660 891534 M 29078 3952 A 4857 6595 -8950887 1091722 M 22141 4720 A 4365 5945 -9809656 1061181 M 14000 5192 A 6753 9190 -4002417 739161 M 4127 15789 A 6753 9190 9459261 711490","stroked":true,"w":43200,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"horizontalScroll":{"guides":["a:pin 0 adj 25000","ch:*/ ss a 100000","ch2:*/ ch 1 2","ch4:*/ ch 1 4","y3:+- ch ch2 0","y4:+- ch ch 0","y6:+- b 0 ch","y7:+- b 0 ch2","y5:+- y6 0 ch2","x3:+- r 0 ch","x4:+- r 0 ch2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r ch2 A ch2 ch2 0 cd4 L x4 ch2 A ch4 ch4 0 cd2 L x3 ch L ch2 ch A ch2 ch2 3cd4 -5400000 L l y7 A ch2 ch2 cd2 -10800000 L ch y6 L x4 y6 A ch2 ch2 cd4 -5400000 Z M ch2 y4 A ch2 ch2 cd4 -5400000 A ch4 ch4 0 -10800000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M ch2 y4 A ch2 ch2 cd4 -5400000 A ch4 ch4 0 -10800000 Z M x4 ch A ch2 ch2 cd4 -16200000 A ch4 ch4 cd2 -10800000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l y3 A ch2 ch2 cd2 cd4 L x3 ch L x3 ch2 A ch2 ch2 cd2 cd2 L r y5 A ch2 ch2 0 cd4 L ch y6 L ch y7 A ch2 ch2 0 cd2 Z M x3 ch L x4 ch A ch2 ch2 cd4 -5400000 M x4 ch L x4 ch2 A ch4 ch4 0 cd2 M ch2 y4 L ch2 y3 A ch4 ch4 cd2 cd2 A ch2 ch2 0 cd2 M ch y3 L ch y6","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"cube":{"guides":["a:pin 0 adj 100000","y1:*/ ss a 100000","y4:+- b 0 y1","y2:*/ y4 1 2","y3:+/ y1 b 2","x4:+- r 0 y1","x2:*/ x4 1 2","x3:+/ y1 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x4 y1 L x4 b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x4 y1 L r t L r y4 L x4 b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN_LESS","filled":true,"h":-1,"path":"M l y1 L y1 t L r t L x4 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l y1 L y1 t L r t L r y4 L x4 b L l b Z M l y1 L x4 y1 L r t M x4 y1 L x4 b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"homePlate":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","dx1:*/ ss a 100000","x1:+- r 0 dx1","ir:+/ x1 r 2","x2:*/ x1 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L r vc L x1 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"pentagon":{"guides":["swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:cos swd2 1080000","dx2:cos swd2 18360000","dy1:sin shd2 1080000","dy2:sin shd2 18360000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc 0 dy2","it:*/ y1 dx2 dx1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L hc t L x4 y1 L x3 y2 L x2 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["hf:val 105146","vf:val 110557"]},"verticalScroll":{"guides":["a:pin 0 adj 25000","ch:*/ ss a 100000","ch2:*/ ch 1 2","ch4:*/ ch 1 4","x3:+- ch ch2 0","x4:+- ch ch 0","x6:+- r 0 ch","x7:+- r 0 ch2","x5:+- x6 0 ch2","y3:+- b 0 ch","y4:+- b 0 ch2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M ch2 b A ch2 ch2 cd4 -5400000 L ch2 y4 A ch4 ch4 cd4 -10800000 L ch y3 L ch ch2 A ch2 ch2 cd2 cd4 L x7 t A ch2 ch2 3cd4 cd2 L x6 ch L x6 y4 A ch2 ch2 0 cd4 Z M x4 ch2 A ch2 ch2 0 cd4 A ch4 ch4 cd4 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x4 ch2 A ch2 ch2 0 cd4 A ch4 ch4 cd4 cd2 Z M ch y4 A ch2 ch2 0 3cd4 A ch4 ch4 3cd4 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ch y3 L ch ch2 A ch2 ch2 cd2 cd4 L x7 t A ch2 ch2 3cd4 cd2 L x6 ch L x6 y4 A ch2 ch2 0 cd4 L ch2 b A ch2 ch2 cd4 cd2 Z M x3 t A ch2 ch2 3cd4 cd2 A ch4 ch4 cd4 cd2 L x4 ch2 M x6 ch L x3 ch M ch2 y3 A ch4 ch4 3cd4 cd2 L ch y4 M ch2 b A ch2 ch2 cd4 -5400000 L ch y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"roundRect":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd2 cd4 L x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4 L x1 b A x1 x1 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"stripedRightArrow":{"guides":["maxAdj2:*/ 84375 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","x4:*/ ss 5 32","dx5:*/ ss a2 100000","x5:+- r 0 dx5","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx6:*/ dy1 dx5 hd2","x6:+- r 0 dx6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L ssd32 y1 L ssd32 y2 L l y2 Z M ssd16 y1 L ssd8 y1 L ssd8 y2 L ssd16 y2 Z M x4 y1 L x5 y1 L x5 t L r vc L x5 b L x5 y2 L x4 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartSort":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":false,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":2,"path":"M 0 1 L 2 1","stroked":true,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"mathPlus":{"guides":["a1:pin 0 adj1 73490","dx1:*/ w 73490 200000","dy1:*/ h 73490 200000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dx2","y3:+- vc dx2 0","y4:+- vc dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L x2 y2 L x2 y1 L x3 y1 L x3 y2 L x4 y2 L x4 y3 L x3 y3 L x3 y4 L x2 y4 L x2 y3 L x1 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"swooshArrow":{"guides":["a1:pin 1 adj1 75000","maxAdj2:*/ 70000 w ss","a2:pin 0 adj2 maxAdj2","ad1:*/ h a1 100000","ad2:*/ ss a2 100000","xB:+- r 0 ad2","yB:+- t ssd8 0","alfa:*/ cd4 1 14","dx0:tan ssd8 alfa","xC:+- xB 0 dx0","dx1:tan ad1 alfa","yF:+- yB ad1 0","xF:+- xB dx1 0","xE:+- xF dx0 0","yE:+- yF ssd8 0","dy2:+- yE 0 t","dy22:*/ dy2 1 2","dy3:*/ h 1 20","yD:+- t dy22 dy3","dy4:*/ hd6 1 1","yP1:+- hd6 dy4 0","xP1:val wd6","dy5:*/ hd6 1 2","yP2:+- yF dy5 0","xP2:val wd4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b Q xP1 yP1 xB yB L xC t L r yD L xE yE L xF yF Q xP2 yP2 l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 16667"]},"wedgeRectCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","dx:+- xPos 0 hc","dy:+- yPos 0 vc","dq:*/ dxPos h w","ady:abs dyPos","adq:abs dq","dz:+- ady 0 adq","xg1:?: dxPos 7 2","xg2:?: dxPos 10 5","x1:*/ w xg1 12","x2:*/ w xg2 12","yg1:?: dyPos 7 2","yg2:?: dyPos 10 5","y1:*/ h yg1 12","y2:*/ h yg2 12","t1:?: dxPos l xPos","xl:?: dz l t1","t2:?: dyPos x1 xPos","xt:?: dz t2 x1","t3:?: dxPos xPos r","xr:?: dz r t3","t4:?: dyPos xPos x1","xb:?: dz t4 x1","t5:?: dxPos y1 yPos","yl:?: dz y1 t5","t6:?: dyPos t yPos","yt:?: dz t6 t","t7:?: dxPos yPos y1","yr:?: dz y1 t7","t8:?: dyPos yPos b","yb:?: dz t8 b"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L xt yt L x2 t L r t L r y1 L xr yr L r y2 L r b L x2 b L xb yb L x1 b L l b L l y2 L xl yl L l y1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"circularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","maxAng:abs u21","aAng:pin 0 adj2 maxAng","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","wtE:sin rw1 stAng","htE:cos rh1 stAng","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng:?: ist0 ist0 ist1","isw1:+- stAng 0 istAng","isw2:+- isw1 0 21600000","iswAng:?: isw1 isw2 isw1","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","sw0:+- en2 0 stAng","sw1:+- sw0 21600000 0","swAng:?: sw0 sw0 sw1","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","aI:+- stAng 0 cd4","aA:+- ptAng cd4 0","aB:+- ptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xE yE A rw1 rh1 stAng swAng L xGp yGp L xA yA L xBp yBp L xC yC A rw2 rh2 istAng iswAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 1142319","adj3:val 20457681","adj4:val 10800000","adj5:val 12500"]},"moon":{"guides":["a:pin 0 adj 87500","g0:*/ ss a 100000","g0w:*/ g0 w ss","g1:+- ss 0 g0","g2:*/ g0 g0 g1","g3:*/ ss ss g1","g4:*/ g3 2 1","g5:+- g4 0 g2","g6:+- g5 0 g0","g6w:*/ g6 w ss","g7:*/ g5 1 2","g8:+- g7 0 g0","dy1:*/ g8 hd2 ss","g10h:+- vc 0 dy1","g11h:+- vc dy1 0","g12:*/ g0 9598 32768","g12w:*/ g12 w ss","g13:+- ss 0 g12","q1:*/ ss ss 1","q2:*/ g13 g13 1","q3:+- q1 0 q2","q4:sqrt q3","dy4:*/ q4 hd2 ss","g15h:+- vc 0 dy4","g16h:+- vc dy4 0","g17w:+- g6w 0 g0w","g18w:*/ g17w 1 2","dx2p:+- g0w g18w w","dx2:*/ dx2p -1 1","dy2:*/ hd2 -1 1","stAng1:at2 dx2 dy2","enAngp1:at2 dx2 hd2","enAng1:+- enAngp1 0 21600000","swAng1:+- enAng1 0 stAng1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A w hd2 cd4 cd2 A g18w dy1 stAng1 swAng1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"leftRightCircularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","maxAng:abs u21","aAng:pin 0 adj2 maxAng","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","lptAng:+- stAng 0 aAng","wtL:sin rw3 lptAng","htL:cos rh3 lptAng","dxL:cat2 rw3 htL wtL","dyL:sat2 rh3 htL wtL","xL:+- hc dxL 0","yL:+- vc dyL 0","dxK:cos thh lptAng","dyK:sin thh lptAng","xK:+- xI dxK 0","yK:+- yI dyK 0","dxJ:cos thh lptAng","dyJ:sin thh lptAng","xJ:+- xI 0 dxJ 0","yJ:+- yI 0 dyJ 0","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","od0:+- en2 0 enAng","od1:+- od0 21600000 0","od2:?: od0 od0 od1","st0:+- stAng 0 od2","st1:+- st0 21600000 0","st2:?: st0 st0 st1","sw0:+- en2 0 st2","sw1:+- sw0 21600000 0","swAng:?: sw0 sw0 sw1","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng:?: ist0 ist0 ist1","id0:+- istAng 0 enAng","id1:+- id0 0 21600000","id2:?: id0 id1 id0","ien0:+- stAng 0 id2","ien1:+- ien0 0 21600000","ien2:?: ien1 ien1 ien0","isw1:+- ien2 0 istAng","isw2:+- isw1 0 21600000","iswAng:?: isw1 isw2 isw1","wtE:sin rw1 st2","htE:cos rh1 st2","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","wtD:sin rw2 ien2","htD:cos rh2 ien2","dxD:cat2 rw2 htD wtD","dyD:sat2 rh2 htD wtD","xD:+- hc dxD 0","yD:+- vc dyD 0","xKp:?: p5 xE xK","yKp:?: p5 yE yK","xJp:?: p5 xD xJ","yJp:?: p5 yD yJ","aL:+- lptAng 0 cd4","aA:+- ptAng cd4 0","aB:+- ptAng cd2 0","aJ:+- lptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xL yL L xKp yKp L xE yE A rw1 rh1 st2 swAng L xGp yGp L xA yA L xBp yBp L xC yC A rw2 rh2 istAng iswAng L xJp yJp Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 1142319","adj3:val 20457681","adj4:val 11942319","adj5:val 12500"]},"uturnArrow":{"guides":["a2:pin 0 adj2 25000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q2:*/ a1 ss h","q3:+- 100000 0 q2","maxAdj3:*/ q3 h ss","a3:pin 0 adj3 maxAdj3","q1:+- a3 a1 0","minAdj5:*/ q1 ss h","a5:pin minAdj5 adj5 100000","th:*/ ss a1 100000","aw2:*/ ss a2 100000","th2:*/ th 1 2","dh2:+- aw2 0 th2","y5:*/ h a5 100000","ah:*/ ss a3 100000","y4:+- y5 0 ah","x9:+- r 0 dh2","bw:*/ x9 1 2","bs:min bw y4","maxAdj4:*/ bs 100000 ss","a4:pin 0 adj4 maxAdj4","bd:*/ ss a4 100000","bd3:+- bd 0 th","bd2:max bd3 0","x3:+- th bd2 0","x8:+- r 0 aw2","x6:+- x8 0 aw2","x7:+- x6 dh2 0","x4:+- x9 0 bd","x5:+- x7 0 bd2","cx:+/ th x7 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l bd A bd bd cd2 cd4 L x4 t A bd bd 3cd4 cd4 L x9 y4 L r y4 L x8 y5 L x6 y4 L x7 y4 L x7 x3 A bd2 bd2 0 -5400000 L x3 th A bd2 bd2 3cd4 -5400000 L th b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 43750","adj5:val 75000"]},"heptagon":{"guides":["swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:*/ swd2 97493 100000","dx2:*/ swd2 78183 100000","dx3:*/ swd2 43388 100000","dy1:*/ shd2 62349 100000","dy2:*/ shd2 22252 100000","dy3:*/ shd2 90097 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc dy2 0","y3:+- svc dy3 0","ib:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L x2 y1 L hc t L x5 y1 L x6 y2 L x4 y3 L x3 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["hf:val 102572","vf:val 105210"]},"star16":{"guides":["a:pin 0 adj 50000","dx1:*/ wd2 92388 100000","dx2:*/ wd2 70711 100000","dx3:*/ wd2 38268 100000","dy1:*/ hd2 92388 100000","dy2:*/ hd2 70711 100000","dy3:*/ hd2 38268 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc dy3 0","y5:+- vc dy2 0","y6:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 98079 100000","sdx2:*/ iwd2 83147 100000","sdx3:*/ iwd2 55557 100000","sdx4:*/ iwd2 19509 100000","sdy1:*/ ihd2 98079 100000","sdy2:*/ ihd2 83147 100000","sdy3:*/ ihd2 55557 100000","sdy4:*/ ihd2 19509 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc sdx4 0","sx6:+- hc sdx3 0","sx7:+- hc sdx2 0","sx8:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc sdy4 0","sy6:+- vc sdy3 0","sy7:+- vc sdy2 0","sy8:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy4 L x1 y3 L sx2 sy3 L x2 y2 L sx3 sy2 L x3 y1 L sx4 sy1 L hc t L sx5 sy1 L x4 y1 L sx6 sy2 L x5 y2 L sx7 sy3 L x6 y3 L sx8 sy4 L r vc L sx8 sy5 L x6 y4 L sx7 sy6 L x5 y5 L sx6 sy7 L x4 y6 L sx5 sy8 L hc b L sx4 sy8 L x3 y6 L sx3 sy7 L x2 y5 L sx2 sy6 L x1 y4 L sx1 sy5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"accentCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"curvedRightArrow":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 a2","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","hR:+- hd2 0 q1","q7:*/ hR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idx:*/ q11 w q7","maxAdj3:*/ 100000 idx ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss a3 100000","y3:+- hR th 0","q2:*/ w w 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dy:*/ q5 hR w","y5:+- hR dy 0","y7:+- y3 dy 0","q6:+- aw 0 th","dh:*/ q6 1 2","y4:+- y5 0 dh","y8:+- y7 dh 0","aw2:*/ aw 1 2","y6:+- b 0 aw2","x1:+- r 0 ah","swAng:at2 ah dy","stAng:+- cd2 0 swAng","mswAng:+- 0 0 swAng","ix:+- r 0 idx","iy:+/ hR y3 2","q12:*/ th 1 2","dang2:at2 idx q12","swAng2:+- dang2 0 cd4","swAng3:+- cd4 dang2 0","stAng3:+- cd2 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l hR A w hR cd2 mswAng L x1 y4 L r y6 L x1 y8 L x1 y7 A w hR stAng swAng Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M r th A w hR 3cd4 swAng2 A w hR stAng3 swAng3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l hR A w hR cd2 mswAng L x1 y4 L r y6 L x1 y8 L x1 y7 A w hR stAng swAng L l hR A w hR cd2 cd4 L r th A w hR 3cd4 swAng2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"accentCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"actionButtonBackPrevious":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 vc L g12 g9 L g12 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 vc L g12 g9 L g12 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 vc L g12 g9 L g12 g10 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonReturn":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 7 8","g15:*/ g13 3 4","g16:*/ g13 5 8","g17:*/ g13 3 8","g18:*/ g13 1 4","g19:+- g9 g15 0","g20:+- g9 g16 0","g21:+- g9 g18 0","g22:+- g11 g14 0","g23:+- g11 g15 0","g24:+- g11 g16 0","g25:+- g11 g17 0","g26:+- g11 g18 0","g27:*/ g13 1 8"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g12 g21 L g23 g9 L hc g21 L g24 g21 L g24 g20 A g27 g27 0 cd4 L g25 g19 A g27 g27 cd4 cd4 L g26 g21 L g11 g21 L g11 g20 A g17 g17 cd2 -5400000 L hc g10 A g17 g17 cd4 -5400000 L g22 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g12 g21 L g23 g9 L hc g21 L g24 g21 L g24 g20 A g27 g27 0 cd4 L g25 g19 A g27 g27 cd4 cd4 L g26 g21 L g11 g21 L g11 g20 A g17 g17 cd2 -5400000 L hc g10 A g17 g17 cd4 -5400000 L g22 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g12 g21 L g22 g21 L g22 g20 A g17 g17 0 cd4 L g25 g10 A g17 g17 cd4 cd4 L g11 g21 L g26 g21 L g26 g20 A g27 g27 cd2 -5400000 L hc g19 A g27 g27 cd4 -5400000 L g24 g21 L hc g21 L g23 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftUpArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:+- 100000 0 maxAdj1","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 50000","x2:+- r 0 dx2","y2:+- b 0 dx2","dx4:*/ ss a2 100000","x4:+- r 0 dx4","y4:+- b 0 dx4","dx3:*/ ss a1 200000","x3:+- x4 0 dx3","x5:+- x4 dx3 0","y3:+- y4 0 dx3","y5:+- y4 dx3 0","il:*/ dx3 x1 dx4","cx1:+/ x1 x5 2","cy1:+/ x1 y5 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y4 L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L x4 t L r x1 L x5 x1 L x5 y5 L x1 y5 L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"star10":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","dx1:*/ swd2 95106 100000","dx2:*/ swd2 58779 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy1:*/ hd2 80902 100000","dy2:*/ hd2 30902 100000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","iwd2:*/ swd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 80902 100000","sdx2:*/ iwd2 30902 100000","sdy1:*/ ihd2 95106 100000","sdy2:*/ ihd2 58779 100000","sx1:+- hc 0 iwd2","sx2:+- hc 0 sdx1","sx3:+- hc 0 sdx2","sx4:+- hc sdx2 0","sx5:+- hc sdx1 0","sx6:+- hc iwd2 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc sdy2 0","sy4:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L sx2 sy2 L x2 y1 L sx3 sy1 L hc t L sx4 sy1 L x3 y1 L sx5 sy2 L x4 y2 L sx6 vc L x4 y3 L sx5 sy3 L x3 y4 L sx4 sy4 L hc b L sx3 sy4 L x2 y4 L sx2 sy3 L x1 y3 L sx1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 42533","hf:val 105146"]},"accentCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"star12":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 1800000","dy1:sin hd2 3600000","x1:+- hc 0 dx1","x3:*/ w 3 4","x4:+- hc dx1 0","y1:+- vc 0 dy1","y3:*/ h 3 4","y4:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:cos iwd2 900000","sdx2:cos iwd2 2700000","sdx3:cos iwd2 4500000","sdy1:sin ihd2 4500000","sdy2:sin ihd2 2700000","sdy3:sin ihd2 900000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc sdx3 0","sx5:+- hc sdx2 0","sx6:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc sdy3 0","sy5:+- vc sdy2 0","sy6:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy3 L x1 hd4 L sx2 sy2 L wd4 y1 L sx3 sy1 L hc t L sx4 sy1 L x3 y1 L sx5 sy2 L x4 hd4 L sx6 sy3 L r vc L sx6 sy4 L x4 y3 L sx5 sy5 L x3 y4 L sx4 sy6 L hc b L sx3 sy6 L wd4 y4 L sx2 sy5 L x1 y3 L sx1 sy4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"flowChartManualOperation":{"guides":["x3:*/ w 4 5","x4:*/ w 9 10"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 0 L 5 0 L 4 5 L 1 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartManualInput":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 1 L 5 0 L 5 5 L 0 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartPunchedCard":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 1 L 1 0 L 5 0 L 5 5 L 0 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartMultidocument":{"guides":["y2:*/ h 3675 21600","y8:*/ h 20782 21600","x3:*/ w 9298 21600","x4:*/ w 12286 21600","x5:*/ w 18595 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 0 20782 C 9298 23542 9298 18022 18595 18022 L 18595 3675 L 0 3675 Z M 1532 3675 L 1532 1815 L 20000 1815 L 20000 16252 C 19298 16252 18595 16352 18595 16352 L 18595 3675 Z M 2972 1815 L 2972 0 L 21600 0 L 21600 14392 C 20800 14392 20000 14467 20000 14467 L 20000 1815 Z","stroked":false,"w":21600,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":21600,"path":"M 0 3675 L 18595 3675 L 18595 18022 C 9298 18022 9298 23542 0 20782 Z M 1532 3675 L 1532 1815 L 20000 1815 L 20000 16252 C 19298 16252 18595 16352 18595 16352 M 2972 1815 L 2972 0 L 21600 0 L 21600 14392 C 20800 14392 20000 14467 20000 14467","stroked":true,"w":21600,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":21600,"path":"M 0 20782 C 9298 23542 9298 18022 18595 18022 L 18595 16352 C 18595 16352 19298 16252 20000 16252 L 20000 14467 C 20000 14467 20800 14392 21600 14392 L 21600 0 L 2972 0 L 2972 1815 L 1532 1815 L 1532 3675 L 0 3675 Z","stroked":false,"w":21600,"windingRule":1}],"adjusts":[]},"flowChartInternalStorage":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":false,"w":1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":8,"path":"M 1 0 L 1 8 M 0 1 L 8 1","stroked":true,"w":8,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"flowChartPunchedTape":{"guides":["y2:*/ h 9 10","ib:*/ h 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":20,"path":"M 0 2 A 5 2 cd2 -10800000 A 5 2 cd2 cd2 L 20 18 A 5 2 0 -10800000 A 5 2 0 cd2 Z","stroked":true,"w":20,"windingRule":1}],"adjusts":[]},"snip2SameRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","tx1:*/ ss a1 100000","tx2:+- r 0 tx1","bx1:*/ ss a2 100000","bx2:+- r 0 bx1","by1:+- b 0 bx1","d:+- tx1 0 bx1","dx:?: d tx1 bx1","il:*/ dx 1 2","ir:+- r 0 il","it:*/ tx1 1 2","ib:+/ by1 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M tx1 t L tx2 t L r tx1 L r by1 L bx2 b L bx1 b L l by1 L l tx1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"actionButtonBeginning":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 8","g15:*/ g13 1 4","g16:+- g11 g14 0","g17:+- g11 g15 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g11 g9 L g11 g10 L g16 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g11 g9 L g11 g10 L g16 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g16 g10 L g11 g10 L g11 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartTerminator":{"guides":["il:*/ w 1018 21600","ir:*/ w 20582 21600","it:*/ h 3163 21600","ib:*/ h 18437 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 3475 0 L 18125 0 A 3475 10800 3cd4 cd2 L 3475 21600 A 3475 10800 cd4 cd2 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"notchedRightArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx2:*/ ss a2 100000","x2:+- r 0 dx2","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","x1:*/ dy1 dx2 hd2","x3:+- r 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x2 y1 L x2 t L r vc L x2 b L x2 y2 L l y2 L x1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"actionButtonEnd":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 3 4","g15:*/ g13 7 8","g16:+- g11 g14 0","g17:+- g11 g15 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g16 vc L g11 g9 L g11 g10 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g16 vc L g11 g9 L g11 g10 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g16 vc L g11 g10 L g11 g9 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss w","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","x1:*/ ss a3 100000","dx2:*/ w a4 100000","x2:+- r 0 dx2","x3:+/ x2 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x1 y2 L x2 y2 L x2 t L r t L r b L x2 b L x2 y3 L x1 y3 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"mathEqual":{"guides":["a1:pin 0 adj1 36745","2a1:*/ a1 2 1","mAdj2:+- 100000 0 2a1","a2:pin 0 adj2 mAdj2","dy1:*/ h a1 100000","dy2:*/ h a2 200000","dx1:*/ w 73490 200000","y2:+- vc 0 dy2","y3:+- vc dy2 0","y1:+- y2 0 dy1","y4:+- y3 dy1 0","x1:+- hc 0 dx1","x2:+- hc dx1 0","yC1:+/ y1 y2 2","yC2:+/ y3 y4 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x2 y1 L x2 y2 L x1 y2 Z M x1 y3 L x2 y3 L x2 y4 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 11760"]},"sun":{"guides":["a:pin 12500 adj 46875","g0:+- 50000 0 a","g1:*/ g0 30274 32768","g2:*/ g0 12540 32768","g3:+- g1 50000 0","g4:+- g2 50000 0","g5:+- 50000 0 g1","g6:+- 50000 0 g2","g7:*/ g0 23170 32768","g8:+- 50000 g7 0","g9:+- 50000 0 g7","g10:*/ g5 3 4","g11:*/ g6 3 4","g12:+- g10 3662 0","g13:+- g11 3662 0","g14:+- g11 12500 0","g15:+- 100000 0 g10","g16:+- 100000 0 g12","g17:+- 100000 0 g13","g18:+- 100000 0 g14","ox1:*/ w 18436 21600","oy1:*/ h 3163 21600","ox2:*/ w 3163 21600","oy2:*/ h 18436 21600","x8:*/ w g8 100000","x9:*/ w g9 100000","x10:*/ w g10 100000","x12:*/ w g12 100000","x13:*/ w g13 100000","x14:*/ w g14 100000","x15:*/ w g15 100000","x16:*/ w g16 100000","x17:*/ w g17 100000","x18:*/ w g18 100000","x19:*/ w a 100000","wR:*/ w g0 100000","hR:*/ h g0 100000","y8:*/ h g8 100000","y9:*/ h g9 100000","y10:*/ h g10 100000","y12:*/ h g12 100000","y13:*/ h g13 100000","y14:*/ h g14 100000","y15:*/ h g15 100000","y16:*/ h g16 100000","y17:*/ h g17 100000","y18:*/ h g18 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r vc L x15 y18 L x15 y14 Z M ox1 oy1 L x16 y13 L x17 y12 Z M hc t L x18 y10 L x14 y10 Z M ox2 oy1 L x13 y12 L x12 y13 Z M l vc L x10 y14 L x10 y18 Z M ox2 oy2 L x12 y17 L x13 y16 Z M hc b L x14 y15 L x18 y15 Z M ox1 oy2 L x17 y16 L x16 y17 Z M x19 vc A wR hR cd2 21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"triangle":{"guides":["a:pin 0 adj 100000","x1:*/ w a 200000","x2:*/ w a 100000","x3:+- x1 wd2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"gear9":{"guides":["a1:pin 0 adj1 20000","a2:pin 0 adj2 2679","th:*/ ss a1 100000","lFD:*/ ss a2 100000","th2:*/ th 1 2","l2:*/ lFD 1 2","l3:+- th2 l2 0","rh:+- hd2 0 th","rw:+- wd2 0 th","dr:+- rw 0 rh","maxr:?: dr rh rw","ha:at2 maxr l3","aA1:+- 18600000 0 ha","aD1:+- 18600000 ha 0","ta11:cos rw aA1","ta12:sin rh aA1","bA1:at2 ta11 ta12","cta1:cos rh bA1","sta1:sin rw bA1","ma1:mod cta1 sta1 0","na1:*/ rw rh ma1","dxa1:cos na1 bA1","dya1:sin na1 bA1","xA1:+- hc dxa1 0","yA1:+- vc dya1 0","td11:cos rw aD1","td12:sin rh aD1","bD1:at2 td11 td12","ctd1:cos rh bD1","std1:sin rw bD1","md1:mod ctd1 std1 0","nd1:*/ rw rh md1","dxd1:cos nd1 bD1","dyd1:sin nd1 bD1","xD1:+- hc dxd1 0","yD1:+- vc dyd1 0","xAD1:+- xA1 0 xD1","yAD1:+- yA1 0 yD1","lAD1:mod xAD1 yAD1 0","a1:at2 yAD1 xAD1","dxF1:sin lFD a1","dyF1:cos lFD a1","xF1:+- xD1 dxF1 0","yF1:+- yD1 dyF1 0","xE1:+- xA1 0 dxF1","yE1:+- yA1 0 dyF1","yC1t:sin th a1","xC1t:cos th a1","yC1:+- yF1 yC1t 0","xC1:+- xF1 0 xC1t","yB1:+- yE1 yC1t 0","xB1:+- xE1 0 xC1t","aA2:+- 21000000 0 ha","aD2:+- 21000000 ha 0","ta21:cos rw aA2","ta22:sin rh aA2","bA2:at2 ta21 ta22","cta2:cos rh bA2","sta2:sin rw bA2","ma2:mod cta2 sta2 0","na2:*/ rw rh ma2","dxa2:cos na2 bA2","dya2:sin na2 bA2","xA2:+- hc dxa2 0","yA2:+- vc dya2 0","td21:cos rw aD2","td22:sin rh aD2","bD2:at2 td21 td22","ctd2:cos rh bD2","std2:sin rw bD2","md2:mod ctd2 std2 0","nd2:*/ rw rh md2","dxd2:cos nd2 bD2","dyd2:sin nd2 bD2","xD2:+- hc dxd2 0","yD2:+- vc dyd2 0","xAD2:+- xA2 0 xD2","yAD2:+- yA2 0 yD2","lAD2:mod xAD2 yAD2 0","a2:at2 yAD2 xAD2","dxF2:sin lFD a2","dyF2:cos lFD a2","xF2:+- xD2 dxF2 0","yF2:+- yD2 dyF2 0","xE2:+- xA2 0 dxF2","yE2:+- yA2 0 dyF2","yC2t:sin th a2","xC2t:cos th a2","yC2:+- yF2 yC2t 0","xC2:+- xF2 0 xC2t","yB2:+- yE2 yC2t 0","xB2:+- xE2 0 xC2t","swAng1:+- bA2 0 bD1","aA3:+- 1800000 0 ha","aD3:+- 1800000 ha 0","ta31:cos rw aA3","ta32:sin rh aA3","bA3:at2 ta31 ta32","cta3:cos rh bA3","sta3:sin rw bA3","ma3:mod cta3 sta3 0","na3:*/ rw rh ma3","dxa3:cos na3 bA3","dya3:sin na3 bA3","xA3:+- hc dxa3 0","yA3:+- vc dya3 0","td31:cos rw aD3","td32:sin rh aD3","bD3:at2 td31 td32","ctd3:cos rh bD3","std3:sin rw bD3","md3:mod ctd3 std3 0","nd3:*/ rw rh md3","dxd3:cos nd3 bD3","dyd3:sin nd3 bD3","xD3:+- hc dxd3 0","yD3:+- vc dyd3 0","xAD3:+- xA3 0 xD3","yAD3:+- yA3 0 yD3","lAD3:mod xAD3 yAD3 0","a3:at2 yAD3 xAD3","dxF3:sin lFD a3","dyF3:cos lFD a3","xF3:+- xD3 dxF3 0","yF3:+- yD3 dyF3 0","xE3:+- xA3 0 dxF3","yE3:+- yA3 0 dyF3","yC3t:sin th a3","xC3t:cos th a3","yC3:+- yF3 yC3t 0","xC3:+- xF3 0 xC3t","yB3:+- yE3 yC3t 0","xB3:+- xE3 0 xC3t","swAng2:+- bA3 0 bD2","aA4:+- 4200000 0 ha","aD4:+- 4200000 ha 0","ta41:cos rw aA4","ta42:sin rh aA4","bA4:at2 ta41 ta42","cta4:cos rh bA4","sta4:sin rw bA4","ma4:mod cta4 sta4 0","na4:*/ rw rh ma4","dxa4:cos na4 bA4","dya4:sin na4 bA4","xA4:+- hc dxa4 0","yA4:+- vc dya4 0","td41:cos rw aD4","td42:sin rh aD4","bD4:at2 td41 td42","ctd4:cos rh bD4","std4:sin rw bD4","md4:mod ctd4 std4 0","nd4:*/ rw rh md4","dxd4:cos nd4 bD4","dyd4:sin nd4 bD4","xD4:+- hc dxd4 0","yD4:+- vc dyd4 0","xAD4:+- xA4 0 xD4","yAD4:+- yA4 0 yD4","lAD4:mod xAD4 yAD4 0","a4:at2 yAD4 xAD4","dxF4:sin lFD a4","dyF4:cos lFD a4","xF4:+- xD4 dxF4 0","yF4:+- yD4 dyF4 0","xE4:+- xA4 0 dxF4","yE4:+- yA4 0 dyF4","yC4t:sin th a4","xC4t:cos th a4","yC4:+- yF4 yC4t 0","xC4:+- xF4 0 xC4t","yB4:+- yE4 yC4t 0","xB4:+- xE4 0 xC4t","swAng3:+- bA4 0 bD3","aA5:+- 6600000 0 ha","aD5:+- 6600000 ha 0","ta51:cos rw aA5","ta52:sin rh aA5","bA5:at2 ta51 ta52","td51:cos rw aD5","td52:sin rh aD5","bD5:at2 td51 td52","xD5:+- w 0 xA4","xC5:+- w 0 xB4","xB5:+- w 0 xC4","swAng4:+- bA5 0 bD4","aD6:+- 9000000 ha 0","td61:cos rw aD6","td62:sin rh aD6","bD6:at2 td61 td62","xD6:+- w 0 xA3","xC6:+- w 0 xB3","xB6:+- w 0 xC3","aD7:+- 11400000 ha 0","td71:cos rw aD7","td72:sin rh aD7","bD7:at2 td71 td72","xD7:+- w 0 xA2","xC7:+- w 0 xB2","xB7:+- w 0 xC2","aD8:+- 13800000 ha 0","td81:cos rw aD8","td82:sin rh aD8","bD8:at2 td81 td82","xA8:+- w 0 xD1","xD8:+- w 0 xA1","xC8:+- w 0 xB1","xB8:+- w 0 xC1","aA9:+- 3cd4 0 ha","aD9:+- 3cd4 ha 0","td91:cos rw aD9","td92:sin rh aD9","bD9:at2 td91 td92","ctd9:cos rh bD9","std9:sin rw bD9","md9:mod ctd9 std9 0","nd9:*/ rw rh md9","dxd9:cos nd9 bD9","dyd9:sin nd9 bD9","xD9:+- hc dxd9 0","yD9:+- vc dyd9 0","ta91:cos rw aA9","ta92:sin rh aA9","bA9:at2 ta91 ta92","xA9:+- hc 0 dxd9","xF9:+- xD9 0 lFD","xE9:+- xA9 lFD 0","yC9:+- yD9 0 th","swAng5:+- bA9 0 bD8","xCxn1:+/ xB1 xC1 2","yCxn1:+/ yB1 yC1 2","xCxn2:+/ xB2 xC2 2","yCxn2:+/ yB2 yC2 2","xCxn3:+/ xB3 xC3 2","yCxn3:+/ yB3 yC3 2","xCxn4:+/ xB4 xC4 2","yCxn4:+/ yB4 yC4 2","xCxn5:+/ r 0 xCxn4","xCxn6:+/ r 0 xCxn3","xCxn7:+/ r 0 xCxn2","xCxn8:+/ r 0 xCxn1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA1 yA1 L xB1 yB1 L xC1 yC1 L xD1 yD1 A rw rh bD1 swAng1 L xB2 yB2 L xC2 yC2 L xD2 yD2 A rw rh bD2 swAng2 L xB3 yB3 L xC3 yC3 L xD3 yD3 A rw rh bD3 swAng3 L xB4 yB4 L xC4 yC4 L xD4 yD4 A rw rh bD4 swAng4 L xB5 yC4 L xC5 yB4 L xD5 yA4 A rw rh bD5 swAng3 L xB6 yC3 L xC6 yB3 L xD6 yA3 A rw rh bD6 swAng2 L xB7 yC2 L xC7 yB2 L xD7 yA2 A rw rh bD7 swAng1 L xB8 yC1 L xC8 yB1 L xD8 yA1 A rw rh bD8 swAng5 L xE9 yC9 L xF9 yC9 L xD9 yD9 A rw rh bD9 swAng5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 10000","adj2:val 1763"]},"round1Rect":{"guides":["a:pin 0 adj 50000","dx1:*/ ss a 100000","x1:+- r 0 dx1","idx:*/ dx1 29289 100000","ir:+- r 0 idx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t A dx1 dx1 3cd4 cd4 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"arc":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw11:+- enAng 0 stAng","sw12:+- sw11 21600000 0","swAng:?: sw11 sw11 sw12","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc dx2 0","y2:+- vc dy2 0","sw0:+- 21600000 0 stAng","da1:+- swAng 0 sw0","g1:max x1 x2","ir:?: da1 r g1","sw1:+- cd4 0 stAng","sw2:+- 27000000 0 stAng","sw3:?: sw1 sw1 sw2","da2:+- swAng 0 sw3","g5:max y1 y2","ib:?: da2 b g5","sw4:+- cd2 0 stAng","sw5:+- 32400000 0 stAng","sw6:?: sw4 sw4 sw5","da3:+- swAng 0 sw6","g9:min x1 x2","il:?: da3 l g9","sw7:+- 3cd4 0 stAng","sw8:+- 37800000 0 stAng","sw9:?: sw7 sw7 sw8","da4:+- swAng 0 sw9","g13:min y1 y2","it:?: da4 t g13","cang1:+- stAng 0 cd4","cang2:+- enAng cd4 0","cang3:+/ cang1 cang2 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L hc vc Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16200000","adj2:val 0"]},"upDownArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 50000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss hd2","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:*/ ss a3 100000","y4:+- b 0 y1","dy2:*/ h a4 200000","y2:+- vc 0 dy2","y3:+- vc dy2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L hc t L x4 y1 L x3 y1 L x3 y2 L r y2 L r y3 L x3 y3 L x3 y4 L x4 y4 L hc b L x1 y4 L x2 y4 L x2 y3 L l y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 48123"]},"leftBrace":{"guides":["a2:pin 0 adj2 100000","q1:+- 100000 0 a2","q2:min q1 a2","q3:*/ q2 1 2","maxAdj1:*/ q3 h ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","y3:*/ h a2 100000","y4:+- y3 y1 0","dx1:cos wd2 2700000","dy1:sin y1 2700000","il:+- r 0 dx1","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A wd2 y1 cd4 cd4 L hc y4 A wd2 y1 0 -5400000 A wd2 y1 cd4 -5400000 L hc y1 A wd2 y1 cd2 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r b A wd2 y1 cd4 cd4 L hc y4 A wd2 y1 0 -5400000 A wd2 y1 cd4 -5400000 L hc y1 A wd2 y1 cd2 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 8333","adj2:val 50000"]},"flowChartMagneticTape":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0","ang1:at2 w h"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc b A wd2 hd2 cd4 cd4 A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 ang1 L r ib L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"rightBracket":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 100000","y2:+- b 0 y1","dx1:cos w 2700000","dy1:sin y1 2700000","ir:+- l dx1 0","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t A w y1 3cd4 cd4 L r y2 A w y1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t A w y1 3cd4 cd4 L r y2 A w y1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"nonIsoscelesTrapezoid":{"guides":["maxAdj:*/ 50000 w ss","a1:pin 0 adj1 maxAdj","a2:pin 0 adj2 maxAdj","x1:*/ ss a1 200000","x2:*/ ss a1 100000","dx3:*/ ss a2 100000","x3:+- r 0 dx3","x4:+/ r x3 2","il:*/ wd3 a1 maxAdj","adjm:max a1 a2","it:*/ hd3 adjm maxAdj","irt:*/ wd3 a2 maxAdj","ir:+- r 0 irt"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L x3 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000"]},"ellipseRibbon":{"guides":["a1:pin 0 adj1 100000","a2:pin 25000 adj2 75000","q10:+- 100000 0 a1","q11:*/ q10 1 2","q12:+- a1 0 q11","minAdj3:max 0 q12","a3:pin minAdj3 adj3 a1","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x3:+- x2 wd8 0","x4:+- r 0 x3","x5:+- r 0 x2","x6:+- r 0 wd8","dy1:*/ h a3 100000","f1:*/ 4 dy1 w","q1:*/ x3 x3 w","q2:+- x3 0 q1","y1:*/ f1 q2 1","cx1:*/ x3 1 2","cy1:*/ f1 cx1 1","cx2:+- r 0 cx1","q1:*/ h a1 100000","dy3:+- q1 0 dy1","q3:*/ x2 x2 w","q4:+- x2 0 q3","q5:*/ f1 q4 1","y3:+- q5 dy3 0","q6:+- dy1 dy3 y3","q7:+- q6 dy1 0","cy3:+- q7 dy3 0","rh:+- b 0 q1","q8:*/ dy1 14 16","y2:+/ q8 rh 2","y5:+- q5 rh 0","y6:+- y3 rh 0","cx4:*/ x2 1 2","q9:*/ f1 cx4 1","cy4:+- q9 rh 0","cx5:+- r 0 cx4","cy6:+- cy3 rh 0","y7:+- y1 dy3 0","cy7:+- q1 q1 y7","y8:+- b 0 dy1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r t L x6 y2 L r rh Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l rh L wd8 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y7 L x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 L x4 y7 Q hc cy7 x3 y7 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r t L x6 y2 L r rh Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l rh L wd8 y2 Z M x2 y5 L x2 y3 M x5 y3 L x5 y5 M x3 y1 L x3 y7 M x4 y7 L x4 y1","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 12500"]},"ribbon2":{"guides":["a1:pin 0 adj1 33333","a2:pin 25000 adj2 75000","x10:+- r 0 wd8","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x9:+- hc dx2 0","x3:+- x2 wd32 0","x8:+- x9 0 wd32","x5:+- x2 wd8 0","x6:+- x9 0 wd8","x4:+- x5 0 wd32","x7:+- x6 wd32 0","dy1:*/ h a1 200000","y1:+- b 0 dy1","dy2:*/ h a1 100000","y2:+- b 0 dy2","y4:+- t dy2 0","y3:+/ y4 b 2","hR:*/ h a1 400000","y6:+- b 0 hR","y7:+- y1 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x4 b A wd32 hR cd4 -10800000 L x3 y1 A wd32 hR cd4 cd2 L x8 y2 A wd32 hR 3cd4 cd2 L x7 y1 A wd32 hR 3cd4 -10800000 L r b L x10 y3 L r y4 L x9 y4 L x9 hR A wd32 hR 0 -5400000 L x3 t A wd32 hR 3cd4 -5400000 L x2 y4 L l y4 L wd8 y3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x5 y6 A wd32 hR 0 -5400000 L x3 y1 A wd32 hR cd4 cd2 L x5 y2 Z M x6 y6 A wd32 hR cd2 cd4 L x8 y1 A wd32 hR cd4 -10800000 L x6 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l b L wd8 y3 L l y4 L x2 y4 L x2 hR A wd32 hR cd2 cd4 L x8 t A wd32 hR 3cd4 cd4 L x9 y4 L x9 y4 L r y4 L x10 y3 L r b L x7 b A wd32 hR cd4 cd2 L x8 y1 A wd32 hR cd4 -10800000 L x3 y2 A wd32 hR 3cd4 -10800000 L x4 y1 A wd32 hR 3cd4 cd2 Z M x5 y2 L x5 y6 M x6 y6 L x6 y2 M x2 y7 L x2 y4 M x9 y4 L x9 y7","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 50000"]},"gear6":{"guides":["a1:pin 0 adj1 20000","a2:pin 0 adj2 5358","th:*/ ss a1 100000","lFD:*/ ss a2 100000","th2:*/ th 1 2","l2:*/ lFD 1 2","l3:+- th2 l2 0","rh:+- hd2 0 th","rw:+- wd2 0 th","dr:+- rw 0 rh","maxr:?: dr rh rw","ha:at2 maxr l3","aA1:+- 19800000 0 ha","aD1:+- 19800000 ha 0","ta11:cos rw aA1","ta12:sin rh aA1","bA1:at2 ta11 ta12","cta1:cos rh bA1","sta1:sin rw bA1","ma1:mod cta1 sta1 0","na1:*/ rw rh ma1","dxa1:cos na1 bA1","dya1:sin na1 bA1","xA1:+- hc dxa1 0","yA1:+- vc dya1 0","td11:cos rw aD1","td12:sin rh aD1","bD1:at2 td11 td12","ctd1:cos rh bD1","std1:sin rw bD1","md1:mod ctd1 std1 0","nd1:*/ rw rh md1","dxd1:cos nd1 bD1","dyd1:sin nd1 bD1","xD1:+- hc dxd1 0","yD1:+- vc dyd1 0","xAD1:+- xA1 0 xD1","yAD1:+- yA1 0 yD1","lAD1:mod xAD1 yAD1 0","a1:at2 yAD1 xAD1","dxF1:sin lFD a1","dyF1:cos lFD a1","xF1:+- xD1 dxF1 0","yF1:+- yD1 dyF1 0","xE1:+- xA1 0 dxF1","yE1:+- yA1 0 dyF1","yC1t:sin th a1","xC1t:cos th a1","yC1:+- yF1 yC1t 0","xC1:+- xF1 0 xC1t","yB1:+- yE1 yC1t 0","xB1:+- xE1 0 xC1t","aD6:+- 3cd4 ha 0","td61:cos rw aD6","td62:sin rh aD6","bD6:at2 td61 td62","ctd6:cos rh bD6","std6:sin rw bD6","md6:mod ctd6 std6 0","nd6:*/ rw rh md6","dxd6:cos nd6 bD6","dyd6:sin nd6 bD6","xD6:+- hc dxd6 0","yD6:+- vc dyd6 0","xA6:+- hc 0 dxd6","xF6:+- xD6 0 lFD","xE6:+- xA6 lFD 0","yC6:+- yD6 0 th","swAng1:+- bA1 0 bD6","aA2:+- 1800000 0 ha","aD2:+- 1800000 ha 0","ta21:cos rw aA2","ta22:sin rh aA2","bA2:at2 ta21 ta22","yA2:+- h 0 yD1","td21:cos rw aD2","td22:sin rh aD2","bD2:at2 td21 td22","yD2:+- h 0 yA1","yC2:+- h 0 yB1","yB2:+- h 0 yC1","xB2:val xC1","swAng2:+- bA2 0 bD1","aD3:+- cd4 ha 0","td31:cos rw aD3","td32:sin rh aD3","bD3:at2 td31 td32","yD3:+- h 0 yD6","yB3:+- h 0 yC6","aD4:+- 9000000 ha 0","td41:cos rw aD4","td42:sin rh aD4","bD4:at2 td41 td42","xD4:+- w 0 xD1","xC4:+- w 0 xC1","xB4:+- w 0 xB1","aD5:+- 12600000 ha 0","td51:cos rw aD5","td52:sin rh aD5","bD5:at2 td51 td52","xD5:+- w 0 xA1","xC5:+- w 0 xB1","xB5:+- w 0 xC1","xCxn1:+/ xB1 xC1 2","yCxn1:+/ yB1 yC1 2","yCxn2:+- b 0 yCxn1","xCxn4:+/ r 0 xCxn1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA1 yA1 L xB1 yB1 L xC1 yC1 L xD1 yD1 A rw rh bD1 swAng2 L xC1 yB2 L xB1 yC2 L xA1 yD2 A rw rh bD2 swAng1 L xF6 yB3 L xE6 yB3 L xA6 yD3 A rw rh bD3 swAng1 L xB4 yC2 L xC4 yB2 L xD4 yA2 A rw rh bD4 swAng2 L xB5 yC1 L xC5 yB1 L xD5 yA1 A rw rh bD5 swAng1 L xE6 yC6 L xF6 yC6 L xD6 yD6 A rw rh bD6 swAng1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 15000","adj2:val 3526"]},"leftRightUpArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q1:+- 100000 0 maxAdj1","maxAdj3:*/ q1 1 2","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 100000","x2:+- hc 0 dx2","x5:+- hc dx2 0","dx3:*/ ss a1 200000","x3:+- hc 0 dx3","x4:+- hc dx3 0","x6:+- r 0 x1","dy2:*/ ss a2 50000","y2:+- b 0 dy2","y4:+- b 0 dx2","y3:+- y4 0 dx3","y5:+- y4 dx3 0","il:*/ dx3 x1 dx2","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y4 L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L hc t L x5 x1 L x4 x1 L x4 y3 L x6 y3 L x6 y2 L r y4 L x6 b L x6 y5 L x1 y5 L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"curvedConnector3":{"guides":["x2:*/ w adj1 100000","x1:+/ l x2 2","x3:+/ r x2 2","y3:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x1 t x2 hd4 x2 vc C x2 y3 x3 b r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000"]},"curvedConnector2":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C wd2 t r hd2 r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"curvedConnector5":{"guides":["x3:*/ w adj1 100000","x6:*/ w adj3 100000","x1:+/ x3 x6 2","x2:+/ l x3 2","x4:+/ x3 x1 2","x5:+/ x6 x1 2","x7:+/ x6 r 2","y4:*/ h adj2 100000","y1:+/ t y4 2","y2:+/ t y1 2","y3:+/ y1 y4 2","y5:+/ b y4 2","y6:+/ y5 y4 2","y7:+/ y5 b 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x2 t x3 y2 x3 y1 C x3 y3 x4 y4 x1 y4 C x5 y4 x6 y6 x6 y5 C x6 y7 x7 b r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 50000"]},"downArrow":{"guides":["maxAdj2:*/ 100000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dy1:*/ ss a2 100000","y1:+- b 0 dy1","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy2:*/ x1 dy1 wd2","y2:+- y1 dy2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x1 y1 L x1 t L x2 t L x2 y1 L r y1 L hc b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"curvedConnector4":{"guides":["x2:*/ w adj1 100000","x1:+/ l x2 2","x3:+/ r x2 2","x4:+/ x2 x3 2","x5:+/ x3 r 2","y4:*/ h adj2 100000","y1:+/ t y4 2","y2:+/ t y1 2","y3:+/ y1 y4 2","y5:+/ b y4 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x1 t x2 y2 x2 y1 C x2 y3 x4 y4 x3 y4 C x5 y4 r y5 r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartOnlineStorage":{"guides":["x2:*/ w 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 1 0 L 6 0 A 1 3 3cd4 -10800000 L 1 6 A 1 3 cd4 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"actionButtonDocument":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","dx1:*/ ss 9 32","g11:+- hc 0 dx1","g12:+- hc dx1 0","g13:*/ ss 3 16","g14:+- g12 0 g13","g15:+- g9 g13 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g9 L g14 g9 L g12 g15 L g12 g10 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M g11 g9 L g14 g9 L g14 g15 L g12 g15 L g12 g10 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g14 g9 L g14 g15 L g12 g15 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g9 L g14 g9 L g12 g15 L g12 g10 L g11 g10 Z M g12 g15 L g14 g15 L g14 g9","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"mathDivide":{"guides":["a1:pin 1000 adj1 36745","ma1:+- 0 0 a1","ma3h:+/ 73490 ma1 4","ma3w:*/ 36745 w h","maxAdj3:min ma3h ma3w","a3:pin 1000 adj3 maxAdj3","m4a3:*/ -4 a3 1","maxAdj2:+- 73490 m4a3 a1","a2:pin 0 adj2 maxAdj2","dy1:*/ h a1 200000","yg:*/ h a2 100000","rad:*/ h a3 100000","dx1:*/ w 73490 200000","y3:+- vc 0 dy1","y4:+- vc dy1 0","a:+- yg rad 0","y2:+- y3 0 a","y1:+- y2 0 rad","y5:+- b 0 y1","x1:+- hc 0 dx1","x3:+- hc dx1 0","x2:+- hc 0 rad"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc y1 A rad rad 3cd4 21600000 Z M hc y5 A rad rad cd4 21600000 Z M x1 y3 L x3 y3 L x3 y4 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 5880","adj3:val 11760"]},"decagon":{"guides":["shd2:*/ hd2 vf 100000","dx1:cos wd2 2160000","dx2:cos wd2 4320000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy1:sin shd2 4320000","dy2:sin shd2 2160000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y2 L x2 y1 L x3 y1 L x4 y2 L r vc L x4 y3 L x3 y4 L x2 y4 L x1 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["vf:val 105146"]},"leftArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx2:*/ ss a2 100000","x2:+- l dx2 0","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx1:*/ y1 dx2 hd2","x1:+- x2 0 dx1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x2 t L x2 y1 L r y1 L r y2 L x2 y2 L x2 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartAlternateProcess":{"guides":["x2:+- r 0 ssd6","y2:+- b 0 ssd6","il:*/ ssd6 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l ssd6 A ssd6 ssd6 cd2 cd4 L x2 t A ssd6 ssd6 3cd4 cd4 L r y2 A ssd6 ssd6 0 cd4 L ssd6 b A ssd6 ssd6 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"borderCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"flowChartConnector":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"borderCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"borderCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"diagStripe":{"guides":["a:pin 0 adj 100000","x2:*/ w a 100000","x1:*/ x2 1 2","x3:+/ x2 r 2","y2:*/ h a 100000","y1:*/ y2 1 2","y3:+/ y2 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 t L r t L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"chevron":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 100000","x2:+- r 0 x1","x3:*/ x2 1 2","dx:+- x2 0 x1","il:?: dx x1 l","ir:?: dx x2 r"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x2 t L r vc L x2 b L l b L x1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"cornerTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t L l dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L dx b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L r t L r dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r y1 L r b L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"mathMultiply":{"guides":["a1:pin 0 adj1 51965","th:*/ ss a1 100000","a:at2 w h","sa:sin 1 a","ca:cos 1 a","ta:tan 1 a","dl:mod w h 0","rw:*/ dl 51965 100000","lM:+- dl 0 rw","xM:*/ ca lM 2","yM:*/ sa lM 2","dxAM:*/ sa th 2","dyAM:*/ ca th 2","xA:+- xM 0 dxAM","yA:+- yM dyAM 0","xB:+- xM dxAM 0","yB:+- yM 0 dyAM","xBC:+- hc 0 xB","yBC:*/ xBC ta 1","yC:+- yBC yB 0","xD:+- r 0 xB","xE:+- r 0 xA","yFE:+- vc 0 yA","xFE:*/ yFE 1 ta","xF:+- xE 0 xFE","xL:+- xA xFE 0","yG:+- b 0 yA","yH:+- b 0 yB","yI:+- b 0 yC","xC2:+- r 0 xM","yC3:+- b 0 yM"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA yA L xB yB L hc yC L xD yB L xE yA L xF vc L xE yG L xD yH L hc yI L xB yH L xA yG L xL vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"plaque":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 70711 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd4 -5400000 L x2 t A x1 x1 cd2 -5400000 L r y2 A x1 x1 3cd4 -5400000 L x1 b A x1 x1 0 -5400000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"trapezoid":{"guides":["maxAdj:*/ 50000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 200000","x2:*/ ss a 100000","x3:+- r 0 x2","x4:+- r 0 x1","il:*/ wd3 a maxAdj","it:*/ hd3 a maxAdj","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L x3 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"accentBorderCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"accentBorderCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"teardrop":{"guides":["a:pin 0 adj 200000","r2:sqrt 2","tw:*/ wd2 r2 1","th:*/ hd2 r2 1","sw:*/ tw a 100000","sh:*/ th a 100000","dx1:cos sw 2700000","dy1:sin sh 2700000","x1:+- hc dx1 0","y1:+- vc 0 dy1","x2:+/ hc x1 2","y2:+/ vc y1 2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 Q x2 t x1 y1 Q r y2 r vc A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 100000"]},"accentBorderCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"bentConnector3":{"guides":["x1:*/ w adj1 100000"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 b L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000"]},"hexagon":{"guides":["maxAdj:*/ 50000 w ss","a:pin 0 adj maxAdj","shd2:*/ hd2 vf 100000","x1:*/ ss a 100000","x2:+- r 0 x1","dy1:sin shd2 3600000","y1:+- vc 0 dy1","y2:+- vc dy1 0","q1:*/ maxAdj -1 2","q2:+- a q1 0","q3:?: q2 4 2","q4:?: q2 3 2","q5:?: q2 q1 0","q6:+/ a q5 q1","q7:*/ q6 q4 -1","q8:+- q3 q7 0","il:*/ w q8 24","it:*/ h q8 24","ir:+- r 0 il","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x2 y1 L r vc L x2 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000","vf:val 115470"]},"bentConnector2":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftBracket":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 100000","y2:+- b 0 y1","dx1:cos w 2700000","dy1:sin y1 2700000","il:+- r 0 dx1","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A w y1 cd4 cd4 L l y1 A w y1 cd2 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r b A w y1 cd4 cd4 L l y1 A w y1 cd2 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"mathNotEqual":{"guides":["a1:pin 0 adj1 50000","crAng:pin 4200000 adj2 6600000","2a1:*/ a1 2 1","maxAdj3:+- 100000 0 2a1","a3:pin 0 adj3 maxAdj3","dy1:*/ h a1 100000","dy2:*/ h a3 200000","dx1:*/ w 73490 200000","x1:+- hc 0 dx1","x8:+- hc dx1 0","y2:+- vc 0 dy2","y3:+- vc dy2 0","y1:+- y2 0 dy1","y4:+- y3 dy1 0","cadj2:+- crAng 0 cd4","xadj2:tan hd2 cadj2","len:mod xadj2 hd2 0","bhw:*/ len dy1 hd2","bhw2:*/ bhw 1 2","x7:+- hc xadj2 bhw2","dx67:*/ xadj2 y1 hd2","x6:+- x7 0 dx67","dx57:*/ xadj2 y2 hd2","x5:+- x7 0 dx57","dx47:*/ xadj2 y3 hd2","x4:+- x7 0 dx47","dx37:*/ xadj2 y4 hd2","x3:+- x7 0 dx37","dx27:*/ xadj2 2 1","x2:+- x7 0 dx27","rx7:+- x7 bhw 0","rx6:+- x6 bhw 0","rx5:+- x5 bhw 0","rx4:+- x4 bhw 0","rx3:+- x3 bhw 0","rx2:+- x2 bhw 0","dx7:*/ dy1 hd2 len","rxt:+- x7 dx7 0","lxt:+- rx7 0 dx7","rx:?: cadj2 rxt rx7","lx:?: cadj2 x7 lxt","dy3:*/ dy1 xadj2 len","dy4:+- 0 0 dy3","ry:?: cadj2 dy3 t","ly:?: cadj2 t dy4","dlx:+- w 0 rx","drx:+- w 0 lx","dly:+- h 0 ry","dry:+- h 0 ly","xC1:+/ rx lx 2","xC2:+/ drx dlx 2","yC1:+/ ry ly 2","yC2:+/ y1 y2 2","yC3:+/ y3 y4 2","yC4:+/ dry dly 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x6 y1 L lx ly L rx ry L rx6 y1 L x8 y1 L x8 y2 L rx5 y2 L rx4 y3 L x8 y3 L x8 y4 L rx3 y4 L drx dry L dlx dly L x3 y4 L x1 y4 L x1 y3 L x4 y3 L x5 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 6600000","adj3:val 11760"]},"wedgeEllipseCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","sdx:*/ dxPos h 1","sdy:*/ dyPos w 1","pang:at2 sdx sdy","stAng:+- pang 660000 0","enAng:+- pang 0 660000","dx1:cos wd2 stAng","dy1:sin hd2 stAng","x1:+- hc dx1 0","y1:+- vc dy1 0","dx2:cos wd2 enAng","dy2:sin hd2 enAng","x2:+- hc dx2 0","y2:+- vc dy2 0","stAng1:at2 dx1 dy1","enAng1:at2 dx2 dy2","swAng1:+- enAng1 0 stAng1","swAng2:+- swAng1 21600000 0","swAng:?: swAng1 swAng1 swAng2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xPos yPos L x1 y1 A wd2 hd2 stAng1 swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"pie":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw1:+- enAng 0 stAng","sw2:+- sw1 21600000 0","swAng:?: sw1 sw1 sw2","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","x1:+- hc dx1 0","y1:+- vc dy1 0","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x2:+- hc dx2 0","y2:+- vc dy2 0","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L hc vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 0","adj2:val 16200000"]},"cloud":{"guides":["il:*/ w 2977 21600","it:*/ h 3262 21600","ir:*/ w 17087 21600","ib:*/ h 17337 21600","g27:*/ w 67 21600","g28:*/ h 21577 21600","g29:*/ w 21582 21600","g30:*/ h 1235 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":43200,"path":"M 3900 14370 A 6753 9190 -11429249 7426832 A 5333 7267 -8646143 5396714 A 4365 5945 -8748475 5983381 A 4857 6595 -7859164 7034504 A 5333 7273 -4722533 6541615 A 6775 9220 -2776035 7816140 A 5785 7867 37501 6842000 A 6752 9215 1347096 6910353 A 7720 10543 3974558 4542661 A 4360 5918 -16496525 8804134 A 4345 5945 -14809710 9151131 Z","stroked":true,"w":43200,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":43200,"path":"M 4693 26177 A 4345 5945 5204520 1585770 M 6928 34899 A 4360 5918 4416628 686848 M 16478 39090 A 6752 9215 8257449 844866 M 28827 34751 A 6752 9215 387196 959901 M 34129 22954 A 5785 7867 -4217541 4255042 M 41798 15354 A 5333 7273 1819082 1665090 M 38324 5426 A 4857 6595 -824660 891534 M 29078 3952 A 4857 6595 -8950887 1091722 M 22141 4720 A 4365 5945 -9809656 1061181 M 14000 5192 A 6753 9190 -4002417 739161 M 4127 15789 A 6753 9190 9459261 711490","stroked":true,"w":43200,"windingRule":1}],"adjusts":[]},"curvedLeftArrow":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 a2","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","hR:+- hd2 0 q1","q7:*/ hR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idx:*/ q11 w q7","maxAdj3:*/ 100000 idx ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss a3 100000","y3:+- hR th 0","q2:*/ w w 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dy:*/ q5 hR w","y5:+- hR dy 0","y7:+- y3 dy 0","q6:+- aw 0 th","dh:*/ q6 1 2","y4:+- y5 0 dh","y8:+- y7 dh 0","aw2:*/ aw 1 2","y6:+- b 0 aw2","x1:+- l ah 0","swAng:at2 ah dy","mswAng:+- 0 0 swAng","ix:+- l idx 0","iy:+/ hR y3 2","q12:*/ th 1 2","dang2:at2 idx q12","swAng2:+- dang2 0 swAng","swAng3:+- swAng dang2 0","stAng3:+- 0 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y6 L x1 y4 L x1 y5 A w hR swAng swAng2 A w hR stAng3 swAng3 L x1 y8 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M r y3 A w hR 0 -5400000 L l t A w hR 3cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r y3 A w hR 0 -5400000 L l t A w hR 3cd4 cd4 L r y3 A w hR 0 swAng L x1 y8 L l y6 L x1 y4 L x1 y5 A w hR swAng swAng2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"bentConnector5":{"guides":["x1:*/ w adj1 100000","x3:*/ w adj3 100000","x2:+/ x1 x3 2","y2:*/ h adj2 100000","y1:+/ t y2 2","y3:+/ b y2 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 y2 L x3 y2 L x3 b L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 50000"]},"leftRightArrow":{"guides":["maxAdj2:*/ 50000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","x2:*/ ss a2 100000","x3:+- r 0 x2","dy:*/ h a1 200000","y1:+- vc 0 dy","y2:+- vc dy 0","dx1:*/ y1 x2 hd2","x1:+- x2 0 dx1","x4:+- x3 dx1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x2 t L x2 y1 L x3 y1 L x3 t L r vc L x3 b L x3 y2 L x2 y2 L x2 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"bentConnector4":{"guides":["x1:*/ w adj1 100000","x2:+/ x1 r 2","y2:*/ h adj2 100000","y1:+/ t y2 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 y2 L r y2 L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"noSmoking":{"guides":["a:pin 0 adj 50000","dr:*/ ss a 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","ang:at2 w h","ct:cos ihd2 ang","st:sin iwd2 ang","m:mod ct st 0","n:*/ iwd2 ihd2 m","drd2:*/ dr 1 2","dang:at2 n drd2","dang2:*/ dang 2 1","swAng:+- -10800000 dang2 0","t3:at2 w h","stAng1:+- t3 0 dang","stAng2:+- stAng1 0 cd2","ct1:cos ihd2 stAng1","st1:sin iwd2 stAng1","m1:mod ct1 st1 0","n1:*/ iwd2 ihd2 m1","dx1:cos n1 stAng1","dy1:sin n1 stAng1","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc 0 dx1","y2:+- vc 0 dy1","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z M x1 y1 A iwd2 ihd2 stAng1 swAng Z M x2 y2 A iwd2 ihd2 stAng2 swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 18750"]},"flowChartDecision":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"donut":{"guides":["a:pin 0 adj 50000","dr:*/ ss a 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z M dr vc A iwd2 ihd2 cd2 -5400000 A iwd2 ihd2 cd4 -5400000 A iwd2 ihd2 0 -5400000 A iwd2 ihd2 3cd4 -5400000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"ellipse":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftRightArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 50000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss wd2","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","x1:*/ ss a3 100000","x4:+- r 0 x1","dx2:*/ w a4 200000","x2:+- hc 0 dx2","x3:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x1 y2 L x2 y2 L x2 t L x3 t L x3 y2 L x4 y2 L x4 y1 L r vc L x4 y4 L x4 y3 L x3 y3 L x3 b L x2 b L x2 y3 L x1 y3 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 48123"]},"flowChartSummingJunction":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M il it L ir ib M ir it L il ib","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"squareTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t L dx dx L l dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L dx y1 L dx b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L r t L r dx L x1 dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L r y1 L r b L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"halfFrame":{"guides":["maxAdj2:*/ 100000 w ss","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","g1:*/ h x1 w","g2:+- h 0 g1","maxAdj1:*/ 100000 g2 ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","dx2:*/ y1 w h","x2:+- r 0 dx2","dy2:*/ x1 h w","y2:+- b 0 dy2","cx1:*/ x1 1 2","cy1:+/ y2 b 2","cx2:+/ x2 r 2","cy2:*/ y1 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L x2 y1 L x1 y1 L x1 y2 L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 33333","adj2:val 33333"]},"chartPlus":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 5 0 L 5 10 M 0 5 L 10 5","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"ribbon":{"guides":["a1:pin 0 adj1 33333","a2:pin 25000 adj2 75000","x10:+- r 0 wd8","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x9:+- hc dx2 0","x3:+- x2 wd32 0","x8:+- x9 0 wd32","x5:+- x2 wd8 0","x6:+- x9 0 wd8","x4:+- x5 0 wd32","x7:+- x6 wd32 0","y1:*/ h a1 200000","y2:*/ h a1 100000","y4:+- b 0 y2","y3:*/ y4 1 2","hR:*/ h a1 400000","y5:+- b 0 hR","y6:+- y2 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x4 t A wd32 hR 3cd4 cd2 L x3 y1 A wd32 hR 3cd4 -10800000 L x8 y2 A wd32 hR cd4 -10800000 L x7 y1 A wd32 hR cd4 cd2 L r t L x10 y3 L r y4 L x9 y4 L x9 y5 A wd32 hR 0 cd4 L x3 b A wd32 hR cd4 cd4 L x2 y4 L l y4 L wd8 y3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x5 hR A wd32 hR 0 cd4 L x3 y1 A wd32 hR 3cd4 -10800000 L x5 y2 Z M x6 hR A wd32 hR cd2 -5400000 L x8 y1 A wd32 hR 3cd4 cd2 L x6 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x4 t A wd32 hR 3cd4 cd2 L x3 y1 A wd32 hR 3cd4 -10800000 L x8 y2 A wd32 hR cd4 -10800000 L x7 y1 A wd32 hR cd4 cd2 L r t L x10 y3 L r y4 L x9 y4 L x9 y5 A wd32 hR 0 cd4 L x3 b A wd32 hR cd4 cd4 L x2 y4 L l y4 L wd8 y3 Z M x5 hR L x5 y2 M x6 y2 L x6 hR M x2 y4 L x2 y6 M x9 y6 L x9 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 50000"]},"star4":{"guides":["a:pin 0 adj 50000","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx:cos iwd2 2700000","sdy:sin ihd2 2700000","sx1:+- hc 0 sdx","sx2:+- hc sdx 0","sy1:+- vc 0 sdy","sy2:+- vc sdy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy1 L hc t L sx2 sy1 L r vc L sx2 sy2 L hc b L sx1 sy2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"star5":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:cos swd2 1080000","dx2:cos swd2 18360000","dy1:sin shd2 1080000","dy2:sin shd2 18360000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc 0 dy2","iwd2:*/ swd2 a 50000","ihd2:*/ shd2 a 50000","sdx1:cos iwd2 20520000","sdx2:cos iwd2 3240000","sdy1:sin ihd2 3240000","sdy2:sin ihd2 20520000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc sdx1 0","sy1:+- svc 0 sdy1","sy2:+- svc 0 sdy2","sy3:+- svc ihd2 0","yAdj:+- svc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L sx2 sy1 L hc t L sx3 sy1 L x4 y1 L sx4 sy2 L x3 y2 L hc sy3 L x2 y2 L sx1 sy2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 19098","hf:val 105146","vf:val 110557"]},"flowChartDelay":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L hc t A wd2 hd2 3cd4 cd2 L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"snip2DiagRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","lx1:*/ ss a1 100000","lx2:+- r 0 lx1","ly1:+- b 0 lx1","rx1:*/ ss a2 100000","rx2:+- r 0 rx1","ry1:+- b 0 rx1","d:+- lx1 0 rx1","dx:?: d lx1 rx1","il:*/ dx 1 2","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M lx1 t L rx2 t L r rx1 L r ly1 L lx2 b L rx1 b L l ry1 L l lx1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 0","adj2:val 16667"]},"star8":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 2700000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:sin hd2 2700000","y1:+- vc 0 dy1","y2:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 92388 100000","sdx2:*/ iwd2 38268 100000","sdy1:*/ ihd2 92388 100000","sdy2:*/ ihd2 38268 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc sdy2 0","sy4:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy2 L x1 y1 L sx2 sy1 L hc t L sx3 sy1 L x2 y1 L sx4 sy2 L r vc L sx4 sy3 L x2 y2 L sx3 sy4 L hc b L sx2 sy4 L x1 y2 L sx1 sy3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"heart":{"guides":["dx1:*/ w 49 48","dx2:*/ w 10 48","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- t 0 hd3","il:*/ w 1 6","ir:*/ w 5 6","ib:*/ h 2 3"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc hd4 C x3 y1 x4 hd4 hc b C x1 hd4 x2 y1 hc hd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"plus":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","d:+- w 0 h","il:?: d l x1","ir:?: d r x2","it:?: d x1 t","ib:?: d y2 b"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 L x1 x1 L x1 t L x2 t L x2 x1 L r x1 L r y2 L x2 y2 L x2 b L x1 b L x1 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"star6":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","dx1:cos swd2 1800000","x1:+- hc 0 dx1","x2:+- hc dx1 0","y2:+- vc hd4 0","iwd2:*/ swd2 a 50000","ihd2:*/ hd2 a 50000","sdx2:*/ iwd2 1 2","sx1:+- hc 0 iwd2","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc iwd2 0","sdy1:sin ihd2 3600000","sy1:+- vc 0 sdy1","sy2:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 hd4 L sx2 sy1 L hc t L sx3 sy1 L x2 hd4 L sx4 vc L x2 y2 L sx3 sy2 L hc b L sx2 sy2 L x1 y2 L sx1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 28868","hf:val 115470"]},"smileyFace":{"guides":["a:pin -4653 adj 4653","x1:*/ w 4969 21699","x2:*/ w 6215 21600","x3:*/ w 13135 21600","x4:*/ w 16640 21600","y1:*/ h 7570 21600","y3:*/ h 16515 21600","dy2:*/ h a 100000","y2:+- y3 0 dy2","y4:+- y3 dy2 0","dy3:*/ h a 50000","y5:+- y4 dy3 0","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0","wR:*/ w 1125 21600","hR:*/ h 1125 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x2 y1 A wR hR cd2 21600000 M x3 y1 A wR hR cd2 21600000","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y2 Q hc y5 x4 y2","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 4653"]},"star7":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:*/ swd2 97493 100000","dx2:*/ swd2 78183 100000","dx3:*/ swd2 43388 100000","dy1:*/ shd2 62349 100000","dy2:*/ shd2 22252 100000","dy3:*/ shd2 90097 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc dy2 0","y3:+- svc dy3 0","iwd2:*/ swd2 a 50000","ihd2:*/ shd2 a 50000","sdx1:*/ iwd2 97493 100000","sdx2:*/ iwd2 78183 100000","sdx3:*/ iwd2 43388 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc sdx3 0","sx5:+- hc sdx2 0","sx6:+- hc sdx1 0","sdy1:*/ ihd2 90097 100000","sdy2:*/ ihd2 22252 100000","sdy3:*/ ihd2 62349 100000","sy1:+- svc 0 sdy1","sy2:+- svc 0 sdy2","sy3:+- svc sdy3 0","sy4:+- svc ihd2 0","yAdj:+- svc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L sx1 sy2 L x2 y1 L sx3 sy1 L hc t L sx4 sy1 L x5 y1 L sx6 sy2 L x6 y2 L sx5 sy3 L x4 y3 L hc sy4 L x3 y3 L sx2 sy3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 34601","hf:val 102572","vf:val 105210"]},"snipRoundRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","x1:*/ ss a1 100000","dx2:*/ ss a2 100000","x2:+- r 0 dx2","il:*/ x1 29289 100000","ir:+/ x2 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L x2 t L r dx2 L r b L l b L l x1 A x1 x1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 16667"]},"straightConnector1":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftCircularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","u22:abs u21","minAng:*/ u22 -1 1","u23:abs adj2","a2:*/ u23 -1 1","aAng:pin minAng a2 0","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","wtE:sin rw1 stAng","htE:cos rh1 stAng","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","wtD:sin rw2 stAng","htD:cos rh2 stAng","dxD:cat2 rw2 htD wtD","dyD:sat2 rh2 htD wtD","xD:+- hc dxD 0","yD:+- vc dyD 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng0:?: ist0 ist0 ist1","isw1:+- stAng 0 istAng0","isw2:+- isw1 21600000 0","iswAng0:?: isw1 isw1 isw2","istAng:+- istAng0 iswAng0 0","iswAng:+- 0 0 iswAng0","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","sw0:+- en2 0 stAng","sw1:+- sw0 0 21600000","swAng:?: sw0 sw1 sw0","stAng0:+- stAng swAng 0","swAng0:+- 0 0 swAng","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","aI:+- stAng cd4 0","aA:+- ptAng 0 cd4","aB:+- ptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xE yE L xD yD A rw2 rh2 istAng iswAng L xBp yBp L xA yA L xGp yGp L xF yF A rw1 rh1 stAng0 swAng0 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val -1142319","adj3:val 1142319","adj4:val 10800000","adj5:val 12500"]},"upArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss h","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:*/ ss a3 100000","dy2:*/ h a4 100000","y2:+- b 0 dy2","y3:+/ y2 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L hc t L x4 y1 L x3 y1 L x3 y2 L r y2 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"actionButtonHelp":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g11:+- hc 0 dx2","g13:*/ ss 3 4","g14:*/ g13 1 7","g15:*/ g13 3 14","g16:*/ g13 2 7","g19:*/ g13 3 7","g20:*/ g13 4 7","g21:*/ g13 17 28","g23:*/ g13 21 28","g24:*/ g13 11 14","g27:+- g9 g16 0","g29:+- g9 g21 0","g30:+- g9 g23 0","g31:+- g9 g24 0","g33:+- g11 g15 0","g36:+- g11 g19 0","g37:+- g11 g20 0","g41:*/ g13 1 14","g42:*/ g13 3 28"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartProcess":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"irregularSeal2":{"guides":["x2:*/ w 9722 21600","x5:*/ w 5372 21600","x16:*/ w 11612 21600","x19:*/ w 14640 21600","y2:*/ h 1887 21600","y3:*/ h 6382 21600","y8:*/ h 12877 21600","y14:*/ h 19712 21600","y16:*/ h 18842 21600","y17:*/ h 15935 21600","y24:*/ h 6645 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 11462 4342 L 14790 0 L 14525 5777 L 18007 3172 L 16380 6532 L 21600 6645 L 16985 9402 L 18270 11290 L 16380 12310 L 18877 15632 L 14640 14350 L 14942 17370 L 12180 15935 L 11612 18842 L 9872 17370 L 8700 19712 L 7527 18125 L 4917 21600 L 4805 18240 L 1285 17825 L 3330 15370 L 0 12877 L 3935 11592 L 1172 8270 L 5372 7817 L 4502 3625 L 8550 6382 L 9722 1887 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"rtTriangle":{"guides":["it:*/ h 7 12","ir:*/ w 7 12","ib:*/ h 11 12"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"frame":{"guides":["a1:pin 0 adj1 50000","x1:*/ ss a1 100000","x4:+- r 0 x1","y4:+- b 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M x1 x1 L x1 y4 L x4 y4 L x4 x1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500"]},"irregularSeal1":{"guides":["x5:*/ w 4627 21600","x12:*/ w 8485 21600","x21:*/ w 16702 21600","x24:*/ w 14522 21600","y3:*/ h 6320 21600","y6:*/ h 8615 21600","y9:*/ h 13937 21600","y18:*/ h 13290 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 10800 5800 L 14522 0 L 14155 5325 L 18380 4457 L 16702 7315 L 21097 8137 L 17607 10475 L 21600 13290 L 16837 12942 L 18145 18095 L 14020 14457 L 13247 19737 L 10532 14935 L 8485 21600 L 7715 15627 L 4762 17617 L 5667 13937 L 135 14587 L 3722 11775 L 0 8615 L 4627 7617 L 370 2295 L 7312 6320 L 8352 2295 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"callout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"callout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"foldedCorner":{"guides":["a:pin 0 adj 50000","dy2:*/ ss a 100000","dy1:*/ dy2 1 5","x1:+- r 0 dy2","x2:+- x1 dy1 0","y2:+- b 0 dy2","y1:+- y2 dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r y2 L x1 b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x1 b L x2 y1 L r y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 b L x2 y1 L r y2 L x1 b L l b L l t L r t L r y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"callout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"curvedUpArrow":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 100000","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","wR:+- wd2 0 q1","q7:*/ wR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idy:*/ q11 h q7","maxAdj3:*/ 100000 idy ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss adj3 100000","x3:+- wR th 0","q2:*/ h h 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dx:*/ q5 wR h","x5:+- wR dx 0","x7:+- x3 dx 0","q6:+- aw 0 th","dh:*/ q6 1 2","x4:+- x5 0 dh","x8:+- x7 dh 0","aw2:*/ aw 1 2","x6:+- r 0 aw2","y1:+- t ah 0","swAng:at2 ah dx","mswAng:+- 0 0 swAng","iy:+- t idy 0","ix:+/ wR x3 2","q12:*/ th 1 2","dang2:at2 idy q12","swAng2:+- dang2 0 swAng","mswAng2:+- 0 0 swAng2","stAng3:+- cd4 0 swAng","swAng3:+- swAng dang2 0","stAng2:+- cd4 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x6 t L x8 y1 L x7 y1 A wR h stAng3 swAng3 A wR h stAng2 swAng2 L x4 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M wR b A wR h cd4 cd4 L th t A wR h cd2 -5400000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L x4 y1 L x6 t L x8 y1 L x7 y1 A wR h stAng3 swAng L wR b A wR h cd4 cd4 L th t A wR h cd2 -5400000","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"line":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"downArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss h","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy3:*/ ss a3 100000","y3:+- b 0 dy3","y2:*/ h a4 100000","y1:*/ y2 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r y2 L x3 y2 L x3 y3 L x4 y3 L hc b L x1 y3 L x2 y3 L x2 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"rightBrace":{"guides":["a2:pin 0 adj2 100000","q1:+- 100000 0 a2","q2:min q1 a2","q3:*/ q2 1 2","maxAdj1:*/ q3 h ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","y3:*/ h a2 100000","y2:+- y3 0 y1","y4:+- b 0 y1","dx1:cos wd2 2700000","dy1:sin y1 2700000","ir:+- l dx1 0","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t A wd2 y1 3cd4 cd4 L hc y2 A wd2 y1 cd2 -5400000 A wd2 y1 3cd4 -5400000 L hc y4 A wd2 y1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t A wd2 y1 3cd4 cd4 L hc y2 A wd2 y1 cd2 -5400000 A wd2 y1 3cd4 -5400000 L hc y4 A wd2 y1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 8333","adj2:val 50000"]},"actionButtonSound":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 8","g15:*/ g13 5 16","g16:*/ g13 5 8","g17:*/ g13 11 16","g18:*/ g13 3 4","g19:*/ g13 7 8","g20:+- g9 g14 0","g21:+- g9 g15 0","g22:+- g9 g17 0","g23:+- g9 g19 0","g24:+- g11 g15 0","g25:+- g11 g16 0","g26:+- g11 g18 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g21 L g11 g22 L g24 g22 L g25 g10 L g25 g9 L g24 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 g21 L g11 g22 L g24 g22 L g25 g10 L g25 g9 L g24 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g21 L g24 g21 L g25 g9 L g25 g10 L g24 g22 L g11 g22 Z M g26 g21 L g12 g20 M g26 vc L g12 vc M g26 g22 L g12 g23","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"quadArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q1:+- 100000 0 maxAdj1","maxAdj3:*/ q1 1 2","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 100000","x2:+- hc 0 dx2","x5:+- hc dx2 0","dx3:*/ ss a1 200000","x3:+- hc 0 dx3","x4:+- hc dx3 0","x6:+- r 0 x1","y2:+- vc 0 dx2","y5:+- vc dx2 0","y3:+- vc 0 dx3","y4:+- vc dx3 0","y6:+- b 0 x1","il:*/ dx3 x1 dx2","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L hc t L x5 x1 L x4 x1 L x4 y3 L x6 y3 L x6 y2 L r vc L x6 y5 L x6 y4 L x4 y4 L x4 y6 L x5 y6 L hc b L x2 y6 L x3 y6 L x3 y4 L x1 y4 L x1 y5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 22500","adj2:val 22500","adj3:val 22500"]},"pieWedge":{"guides":["g1:cos w 13500000","g2:sin h 13500000","x1:+- r g1 0","y1:+- b g2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b A w h cd2 cd4 L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"wave":{"guides":["a1:pin 0 adj1 20000","a2:pin -10000 adj2 10000","y1:*/ h a1 100000","dy2:*/ y1 10 3","y2:+- y1 0 dy2","y3:+- y1 dy2 0","y4:+- b 0 y1","y5:+- y4 0 dy2","y6:+- y4 dy2 0","dx1:*/ w a2 100000","of2:*/ w a2 50000","x1:abs dx1","dx2:?: of2 0 of2","x2:+- l 0 dx2","dx5:?: of2 of2 0","x5:+- r 0 dx5","dx3:+/ dx2 x5 3","x3:+- x2 dx3 0","x4:+/ x3 x5 2","x6:+- l dx5 0","x10:+- r dx2 0","x7:+- x6 dx3 0","x8:+/ x7 x10 2","x9:+- r 0 x1","xAdj:+- hc dx1 0","xAdj2:+- hc 0 dx1","il:max x2 x6","ir:min x5 x10","it:*/ h a1 50000","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 y1 C x3 y2 x4 y3 x5 y1 L x10 y4 C x8 y6 x7 y5 x6 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 0"]},"lightningBolt":{"guides":["x1:*/ w 5022 21600","x3:*/ w 8472 21600","x4:*/ w 8757 21600","x5:*/ w 10012 21600","x8:*/ w 12860 21600","x9:*/ w 13917 21600","x11:*/ w 16577 21600","y1:*/ h 3890 21600","y2:*/ h 6080 21600","y4:*/ h 7437 21600","y6:*/ h 9705 21600","y7:*/ h 12007 21600","y10:*/ h 14277 21600","y11:*/ h 14915 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 8472 0 L 12860 6080 L 11050 6797 L 16577 12007 L 14767 12877 L 21600 21600 L 10012 14915 L 12222 13987 L 5022 9705 L 7602 8382 L 0 3890 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"can":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 200000","y2:+- y1 y1 0","y3:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 A wd2 y1 cd2 -10800000 L r y3 A wd2 y1 0 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M l y1 A wd2 y1 cd2 cd2 A wd2 y1 0 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r y1 A wd2 y1 0 cd2 A wd2 y1 cd2 cd2 L r y3 A wd2 y1 0 cd2 L l y1","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"rect":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonMovie":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1455 21600","g15:*/ g13 1905 21600","g16:*/ g13 2325 21600","g17:*/ g13 16155 21600","g18:*/ g13 17010 21600","g19:*/ g13 19335 21600","g20:*/ g13 19725 21600","g21:*/ g13 20595 21600","g22:*/ g13 5280 21600","g23:*/ g13 5730 21600","g24:*/ g13 6630 21600","g25:*/ g13 7492 21600","g26:*/ g13 9067 21600","g27:*/ g13 9555 21600","g28:*/ g13 13342 21600","g29:*/ g13 14580 21600","g30:*/ g13 15592 21600","g31:+- g11 g14 0","g32:+- g11 g15 0","g33:+- g11 g16 0","g34:+- g11 g17 0","g35:+- g11 g18 0","g36:+- g11 g19 0","g37:+- g11 g20 0","g38:+- g11 g21 0","g39:+- g9 g22 0","g40:+- g9 g23 0","g41:+- g9 g24 0","g42:+- g9 g25 0","g43:+- g9 g26 0","g44:+- g9 g27 0","g45:+- g9 g28 0","g46:+- g9 g29 0","g47:+- g9 g30 0","g48:+- g9 g31 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g39 L g11 g44 L g31 g44 L g32 g43 L g33 g43 L g33 g47 L g35 g47 L g35 g45 L g36 g45 L g38 g46 L g12 g46 L g12 g41 L g38 g41 L g37 g42 L g35 g42 L g35 g41 L g34 g40 L g32 g40 L g31 g39 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 g39 L g11 g44 L g31 g44 L g32 g43 L g33 g43 L g33 g47 L g35 g47 L g35 g45 L g36 g45 L g38 g46 L g12 g46 L g12 g41 L g38 g41 L g37 g42 L g35 g42 L g35 g41 L g34 g40 L g32 g40 L g31 g39 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g39 L g31 g39 L g32 g40 L g34 g40 L g35 g41 L g35 g42 L g37 g42 L g38 g41 L g12 g41 L g12 g46 L g38 g46 L g36 g45 L g35 g45 L g35 g47 L g33 g47 L g33 g43 L g32 g43 L g31 g44 L g11 g44 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonHome":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 16","g15:*/ g13 1 8","g16:*/ g13 3 16","g17:*/ g13 5 16","g18:*/ g13 7 16","g19:*/ g13 9 16","g20:*/ g13 11 16","g21:*/ g13 3 4","g22:*/ g13 13 16","g23:*/ g13 7 8","g24:+- g9 g14 0","g25:+- g9 g16 0","g26:+- g9 g17 0","g27:+- g9 g21 0","g28:+- g11 g15 0","g29:+- g11 g18 0","g30:+- g11 g19 0","g31:+- g11 g20 0","g32:+- g11 g22 0","g33:+- g11 g23 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M hc g9 L g11 vc L g28 vc L g28 g10 L g33 g10 L g33 vc L g12 vc L g32 g26 L g32 g24 L g31 g24 L g31 g25 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M g32 g26 L g32 g24 L g31 g24 L g31 g25 Z M g28 vc L g28 g10 L g29 g10 L g29 g27 L g30 g27 L g30 g10 L g33 g10 L g33 vc Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M hc g9 L g11 vc L g12 vc Z M g29 g27 L g30 g27 L g30 g10 L g29 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc g9 L g31 g25 L g31 g24 L g32 g24 L g32 g26 L g12 vc L g33 vc L g33 g10 L g28 g10 L g28 vc L g11 vc Z M g31 g25 L g32 g26 M g33 vc L g28 vc M g29 g10 L g29 g27 L g30 g27 L g30 g10","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftRightRibbon":{"guides":["a3:pin 0 adj3 33333","maxAdj1:+- 100000 0 a3","a1:pin 0 adj1 maxAdj1","w1:+- wd2 0 wd32","maxAdj2:*/ 100000 w1 ss","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","x4:+- r 0 x1","dy1:*/ h a1 200000","dy2:*/ h a3 -200000","ly1:+- vc dy2 dy1","ry4:+- vc dy1 dy2","ly2:+- ly1 dy1 0","ry3:+- b 0 ly2","ly4:*/ ly2 2 1","ry1:+- b 0 ly4","ly3:+- ly4 0 ly1","ry2:+- b 0 ly3","hR:*/ a3 ss 400000","x2:+- hc 0 wd32","x3:+- hc wd32 0","y1:+- ly1 hR 0","y2:+- ry2 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l ly2 L x1 t L x1 ly1 L hc ly1 A wd32 hR 3cd4 cd2 A wd32 hR 3cd4 -10800000 L x4 ry2 L x4 ry1 L r ry3 L x4 b L x4 ry4 L hc ry4 A wd32 hR cd4 cd4 L x2 ly3 L x1 ly3 L x1 ly4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y1 A wd32 hR 0 cd4 A wd32 hR 3cd4 -10800000 L x3 ry2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l ly2 L x1 t L x1 ly1 L hc ly1 A wd32 hR 3cd4 cd2 A wd32 hR 3cd4 -10800000 L x4 ry2 L x4 ry1 L r ry3 L x4 b L x4 ry4 L hc ry4 A wd32 hR cd4 cd4 L x2 ly3 L x1 ly3 L x1 ly4 Z M x3 y1 L x3 ry2 M x2 y2 L x2 ly3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 16667"]},"flowChartInputOutput":{"guides":["x3:*/ w 2 5","x4:*/ w 3 5","x5:*/ w 4 5","x6:*/ w 9 10"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 5 L 1 0 L 5 0 L 4 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"snip1Rect":{"guides":["a:pin 0 adj 50000","dx1:*/ ss a 100000","x1:+- r 0 dx1","it:*/ dx1 1 2","ir:+/ x1 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L r dx1 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"lineInv":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L r t","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"upDownArrow":{"guides":["maxAdj2:*/ 50000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","y2:*/ ss a2 100000","y3:+- b 0 y2","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:*/ x1 y2 wd2","y1:+- y2 0 dy1","y4:+- y3 dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L hc t L r y2 L x2 y2 L x2 y3 L r y3 L hc b L l y3 L x1 y3 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"star24":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 900000","dx2:cos wd2 1800000","dx3:cos wd2 2700000","dx4:val wd4","dx5:cos wd2 4500000","dy1:sin hd2 4500000","dy2:sin hd2 3600000","dy3:sin hd2 2700000","dy4:val hd4","dy5:sin hd2 900000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc 0 dx4","x5:+- hc 0 dx5","x6:+- hc dx5 0","x7:+- hc dx4 0","x8:+- hc dx3 0","x9:+- hc dx2 0","x10:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc 0 dy4","y5:+- vc 0 dy5","y6:+- vc dy5 0","y7:+- vc dy4 0","y8:+- vc dy3 0","y9:+- vc dy2 0","y10:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 99144 100000","sdx2:*/ iwd2 92388 100000","sdx3:*/ iwd2 79335 100000","sdx4:*/ iwd2 60876 100000","sdx5:*/ iwd2 38268 100000","sdx6:*/ iwd2 13053 100000","sdy1:*/ ihd2 99144 100000","sdy2:*/ ihd2 92388 100000","sdy3:*/ ihd2 79335 100000","sdy4:*/ ihd2 60876 100000","sdy5:*/ ihd2 38268 100000","sdy6:*/ ihd2 13053 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc 0 sdx5","sx6:+- hc 0 sdx6","sx7:+- hc sdx6 0","sx8:+- hc sdx5 0","sx9:+- hc sdx4 0","sx10:+- hc sdx3 0","sx11:+- hc sdx2 0","sx12:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc 0 sdy5","sy6:+- vc 0 sdy6","sy7:+- vc sdy6 0","sy8:+- vc sdy5 0","sy9:+- vc sdy4 0","sy10:+- vc sdy3 0","sy11:+- vc sdy2 0","sy12:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy6 L x1 y5 L sx2 sy5 L x2 y4 L sx3 sy4 L x3 y3 L sx4 sy3 L x4 y2 L sx5 sy2 L x5 y1 L sx6 sy1 L hc t L sx7 sy1 L x6 y1 L sx8 sy2 L x7 y2 L sx9 sy3 L x8 y3 L sx10 sy4 L x9 y4 L sx11 sy5 L x10 y5 L sx12 sy6 L r vc L sx12 sy7 L x10 y6 L sx11 sy8 L x9 y7 L sx10 sy9 L x8 y8 L sx9 sy10 L x7 y9 L sx8 sy11 L x6 y10 L sx7 sy12 L hc b L sx6 sy12 L x5 y10 L sx5 sy11 L x4 y9 L sx4 sy10 L x3 y8 L sx3 sy9 L x2 y7 L sx2 sy8 L x1 y6 L sx1 sy7 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"dodecagon":{"guides":["x1:*/ w 2894 21600","x2:*/ w 7906 21600","x3:*/ w 13694 21600","x4:*/ w 18706 21600","y1:*/ h 2894 21600","y2:*/ h 7906 21600","y3:*/ h 13694 21600","y4:*/ h 18706 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x1 y1 L x2 t L x3 t L x4 y1 L r y2 L r y3 L x4 y4 L x3 b L x2 b L x1 y4 L l y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"wedgeRoundRectCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","dq:*/ dxPos h w","ady:abs dyPos","adq:abs dq","dz:+- ady 0 adq","xg1:?: dxPos 7 2","xg2:?: dxPos 10 5","x1:*/ w xg1 12","x2:*/ w xg2 12","yg1:?: dyPos 7 2","yg2:?: dyPos 10 5","y1:*/ h yg1 12","y2:*/ h yg2 12","t1:?: dxPos l xPos","xl:?: dz l t1","t2:?: dyPos x1 xPos","xt:?: dz t2 x1","t3:?: dxPos xPos r","xr:?: dz r t3","t4:?: dyPos xPos x1","xb:?: dz t4 x1","t5:?: dxPos y1 yPos","yl:?: dz y1 t5","t6:?: dyPos t yPos","yt:?: dz t6 t","t7:?: dxPos yPos y1","yr:?: dz y1 t7","t8:?: dyPos yPos b","yb:?: dz t8 b","u1:*/ ss adj3 100000","u2:+- r 0 u1","v2:+- b 0 u1","il:*/ u1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l u1 A u1 u1 cd2 cd4 L x1 t L xt yt L x2 t L u2 t A u1 u1 3cd4 cd4 L r y1 L xr yr L r y2 L r v2 A u1 u1 0 cd4 L x2 b L xb yb L x1 b L u1 b A u1 u1 cd4 cd4 L l y2 L xl yl L l y1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500","adj3:val 16667"]},"round2DiagRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","x1:*/ ss a1 100000","y1:+- b 0 x1","a:*/ ss a2 100000","x2:+- r 0 a","y2:+- b 0 a","dx1:*/ x1 29289 100000","dx2:*/ a 29289 100000","d:+- dx1 0 dx2","dx:?: d dx1 dx2","ir:+- r 0 dx","ib:+- b 0 dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L x2 t A a a 3cd4 cd4 L r y1 A x1 x1 0 cd4 L a b A a a cd4 cd4 L l x1 A x1 x1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"flowChartMagneticDrum":{"guides":["x2:*/ w 2 3"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 A 1 3 cd4 cd2 Z","stroked":false,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 5 6 A 1 3 cd4 cd2","stroked":true,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 A 1 3 cd4 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"flowChartPreparation":{"guides":["x2:*/ w 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 5 L 2 0 L 8 0 L 10 5 L 8 10 L 2 10 Z","stroked":true,"w":10,"windingRule":1}],"adjusts":[]},"ellipseRibbon2":{"guides":["a1:pin 0 adj1 100000","a2:pin 25000 adj2 75000","q10:+- 100000 0 a1","q11:*/ q10 1 2","q12:+- a1 0 q11","minAdj3:max 0 q12","a3:pin minAdj3 adj3 a1","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x3:+- x2 wd8 0","x4:+- r 0 x3","x5:+- r 0 x2","x6:+- r 0 wd8","dy1:*/ h a3 100000","f1:*/ 4 dy1 w","q1:*/ x3 x3 w","q2:+- x3 0 q1","u1:*/ f1 q2 1","y1:+- b 0 u1","cx1:*/ x3 1 2","cu1:*/ f1 cx1 1","cy1:+- b 0 cu1","cx2:+- r 0 cx1","q1:*/ h a1 100000","dy3:+- q1 0 dy1","q3:*/ x2 x2 w","q4:+- x2 0 q3","q5:*/ f1 q4 1","u3:+- q5 dy3 0","y3:+- b 0 u3","q6:+- dy1 dy3 u3","q7:+- q6 dy1 0","cu3:+- q7 dy3 0","cy3:+- b 0 cu3","rh:+- b 0 q1","q8:*/ dy1 14 16","u2:+/ q8 rh 2","y2:+- b 0 u2","u5:+- q5 rh 0","y5:+- b 0 u5","u6:+- u3 rh 0","y6:+- b 0 u6","cx4:*/ x2 1 2","q9:*/ f1 cx4 1","cu4:+- q9 rh 0","cy4:+- b 0 cu4","cx5:+- r 0 cx4","cu6:+- cu3 rh 0","cy6:+- b 0 cu6","u7:+- u1 dy3 0","y7:+- b 0 u7","cu7:+- q1 q1 u7","cy7:+- b 0 cu7"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r b L x6 y2 L r q1 Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l q1 L wd8 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y7 L x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 L x4 y7 Q hc cy7 x3 y7 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l b L wd8 y2 L l q1 Q cx4 cy4 x2 y5 L x2 y6 Q hc cy6 x5 y6 L x5 y5 Q cx5 cy4 r q1 L x6 y2 L r b Q cx2 cy1 x4 y1 L x5 y3 Q hc cy3 x2 y3 L x3 y1 Q cx1 cy1 l b Z M x2 y3 L x2 y5 M x5 y5 L x5 y3 M x3 y7 L x3 y1 M x4 y1 L x4 y7","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 12500"]},"round2SameRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","tx1:*/ ss a1 100000","tx2:+- r 0 tx1","bx1:*/ ss a2 100000","bx2:+- r 0 bx1","by1:+- b 0 bx1","d:+- tx1 0 bx1","tdx:*/ tx1 29289 100000","bdx:*/ bx1 29289 100000","il:?: d tdx bdx","ir:+- r 0 il","ib:+- b 0 bdx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M tx1 t L tx2 t A tx1 tx1 3cd4 cd4 L r by1 A bx1 bx1 0 cd4 L bx1 b A bx1 bx1 cd4 cd4 L l tx1 A tx1 tx1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"mathMinus":{"guides":["a1:pin 0 adj1 100000","dy1:*/ h a1 200000","dx1:*/ w 73490 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","x1:+- hc 0 dx1","x2:+- hc dx1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x2 y1 L x2 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"blockArc":{"guides":["stAng:pin 0 adj1 21599999","istAng:pin 0 adj2 21599999","a3:pin 0 adj3 50000","sw11:+- istAng 0 stAng","sw12:+- sw11 21600000 0","swAng:?: sw11 sw11 sw12","iswAng:+- 0 0 swAng","wt1:sin wd2 stAng","ht1:cos hd2 stAng","wt3:sin wd2 istAng","ht3:cos hd2 istAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","dx3:cat2 wd2 ht3 wt3","dy3:sat2 hd2 ht3 wt3","x1:+- hc dx1 0","y1:+- vc dy1 0","x3:+- hc dx3 0","y3:+- vc dy3 0","dr:*/ ss a3 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","wt2:sin iwd2 istAng","ht2:cos ihd2 istAng","wt4:sin iwd2 stAng","ht4:cos ihd2 stAng","dx2:cat2 iwd2 ht2 wt2","dy2:sat2 ihd2 ht2 wt2","dx4:cat2 iwd2 ht4 wt4","dy4:sat2 ihd2 ht4 wt4","x2:+- hc dx2 0","y2:+- vc dy2 0","x4:+- hc dx4 0","y4:+- vc dy4 0","sw0:+- 21600000 0 stAng","da1:+- swAng 0 sw0","g1:max x1 x2","g2:max x3 x4","g3:max g1 g2","ir:?: da1 r g3","sw1:+- cd4 0 stAng","sw2:+- 27000000 0 stAng","sw3:?: sw1 sw1 sw2","da2:+- swAng 0 sw3","g5:max y1 y2","g6:max y3 y4","g7:max g5 g6","ib:?: da2 b g7","sw4:+- cd2 0 stAng","sw5:+- 32400000 0 stAng","sw6:?: sw4 sw4 sw5","da3:+- swAng 0 sw6","g9:min x1 x2","g10:min x3 x4","g11:min g9 g10","il:?: da3 l g11","sw7:+- 3cd4 0 stAng","sw8:+- 37800000 0 stAng","sw9:?: sw7 sw7 sw8","da4:+- swAng 0 sw9","g13:min y1 y2","g14:min y3 y4","g15:min g13 g14","it:?: da4 t g15","x5:+/ x1 x4 2","y5:+/ y1 y4 2","x6:+/ x3 x2 2","y6:+/ y3 y2 2","cang1:+- stAng 0 cd4","cang2:+- istAng cd4 0","cang3:+/ cang1 cang2 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L x2 y2 A iwd2 ihd2 istAng iswAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 10800000","adj2:val 0","adj3:val 25000"]},"flowChartPredefinedProcess":{"guides":["x2:*/ w 7 8"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":false,"w":1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":8,"path":"M 1 0 L 1 8 M 7 0 L 7 8","stroked":true,"w":8,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"flowChartMagneticDisk":{"guides":["y3:*/ h 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 0 1 A 3 1 cd2 cd2 L 6 5 A 3 1 0 cd2 Z","stroked":false,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 6 1 A 3 1 0 cd2","stroked":true,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 0 1 A 3 1 cd2 cd2 L 6 5 A 3 1 0 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"flowChartOr":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc t L hc b M l vc L r vc","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"chartX":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 0 0 L 10 10 M 0 10 L 10 0","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"flowChartOffpageConnector":{"guides":["y1:*/ h 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 10 0 L 10 8 L 5 10 L 0 8 Z","stroked":true,"w":10,"windingRule":1}],"adjusts":[]},"bevel":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 x1 L x2 x1 L x2 y2 L x1 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN_LESS","filled":true,"h":-1,"path":"M l t L r t L x2 x1 L x1 x1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M l b L x1 y2 L x2 y2 L r b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M l t L x1 x1 L x1 y2 L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M r t L r b L x2 y2 L x2 x1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z M x1 x1 L x2 x1 L x2 y2 L x1 y2 Z M l t L x1 x1 M l b L x1 y2 M r t L x2 x1 M r b L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"rightArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx1:*/ ss a2 100000","x1:+- r 0 dx1","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx2:*/ y1 dx1 hd2","x2:+- x1 dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x1 y1 L x1 t L r vc L x1 b L x1 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"bentArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","a3:pin 0 adj3 50000","th:*/ ss a1 100000","aw2:*/ ss a2 100000","th2:*/ th 1 2","dh2:+- aw2 0 th2","ah:*/ ss a3 100000","bw:+- r 0 ah","bh:+- b 0 dh2","bs:min bw bh","maxAdj4:*/ 100000 bs ss","a4:pin 0 adj4 maxAdj4","bd:*/ ss a4 100000","bd3:+- bd 0 th","bd2:max bd3 0","x3:+- th bd2 0","x4:+- r 0 ah","y3:+- dh2 th 0","y4:+- y3 dh2 0","y5:+- dh2 bd 0","y6:+- y3 bd2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l y5 A bd bd cd2 cd4 L x4 dh2 L x4 t L r aw2 L x4 y4 L x4 y3 L x3 y3 A bd2 bd2 3cd4 -5400000 L th b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 43750"]},"diamond":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L hc t L r vc L hc b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"bracePair":{"guides":["a:pin 0 adj 25000","x1:*/ ss a 100000","x2:*/ ss a 50000","x3:+- r 0 x2","x4:+- r 0 x1","y2:+- vc 0 x1","y3:+- vc x1 0","y4:+- b 0 x1","it:*/ x1 29289 100000","il:+- x1 it 0","ir:+- r 0 il","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 b A x1 x1 cd4 cd4 L x1 y3 A x1 x1 0 -5400000 A x1 x1 cd4 -5400000 L x1 x1 A x1 x1 cd2 cd4 L x3 t A x1 x1 3cd4 cd4 L x4 y2 A x1 x1 cd2 -5400000 A x1 x1 3cd4 -5400000 L x4 y4 A x1 x1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x2 b A x1 x1 cd4 cd4 L x1 y3 A x1 x1 0 -5400000 A x1 x1 cd4 -5400000 L x1 x1 A x1 x1 cd2 cd4 M x3 t A x1 x1 3cd4 cd4 L x4 y2 A x1 x1 cd2 -5400000 A x1 x1 3cd4 -5400000 L x4 y4 A x1 x1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"flowChartDocument":{"guides":["y1:*/ h 17322 21600","y2:*/ h 20172 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 0 0 L 21600 0 L 21600 17322 C 10800 17322 10800 23922 0 20172 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"bentUpArrow":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","a3:pin 0 adj3 50000","y1:*/ ss a3 100000","dx1:*/ ss a2 50000","x1:+- r 0 dx1","dx3:*/ ss a2 100000","x3:+- r 0 dx3","dx2:*/ ss a1 200000","x2:+- x3 0 dx2","x4:+- x3 dx2 0","dy2:*/ ss a1 100000","y2:+- b 0 dy2","x0:*/ x4 1 2","y3:+/ y2 b 2","y15:+/ y1 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L x3 t L r y1 L x4 y1 L x4 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"octagon":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 1 2","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 L x1 t L x2 t L r x1 L r y2 L x2 b L x1 b L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 29289"]},"chord":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw1:+- enAng 0 stAng","sw2:+- sw1 21600000 0","swAng:?: sw1 sw1 sw2","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc dx2 0","y2:+- vc dy2 0","x3:+/ x1 x2 2","y3:+/ y1 y2 2","midAng0:*/ swAng 1 2","midAng:+- stAng midAng0 cd2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 2700000","adj2:val 16200000"]},"flowChartCollate":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 1 L 2 2 L 0 2 L 1 1 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"flowChartExtract":{"guides":["x2:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 2 L 1 0 L 2 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"star32":{"guides":["a:pin 0 adj 50000","dx1:*/ wd2 98079 100000","dx2:*/ wd2 92388 100000","dx3:*/ wd2 83147 100000","dx4:cos wd2 2700000","dx5:*/ wd2 55557 100000","dx6:*/ wd2 38268 100000","dx7:*/ wd2 19509 100000","dy1:*/ hd2 98079 100000","dy2:*/ hd2 92388 100000","dy3:*/ hd2 83147 100000","dy4:sin hd2 2700000","dy5:*/ hd2 55557 100000","dy6:*/ hd2 38268 100000","dy7:*/ hd2 19509 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc 0 dx4","x5:+- hc 0 dx5","x6:+- hc 0 dx6","x7:+- hc 0 dx7","x8:+- hc dx7 0","x9:+- hc dx6 0","x10:+- hc dx5 0","x11:+- hc dx4 0","x12:+- hc dx3 0","x13:+- hc dx2 0","x14:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc 0 dy4","y5:+- vc 0 dy5","y6:+- vc 0 dy6","y7:+- vc 0 dy7","y8:+- vc dy7 0","y9:+- vc dy6 0","y10:+- vc dy5 0","y11:+- vc dy4 0","y12:+- vc dy3 0","y13:+- vc dy2 0","y14:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 99518 100000","sdx2:*/ iwd2 95694 100000","sdx3:*/ iwd2 88192 100000","sdx4:*/ iwd2 77301 100000","sdx5:*/ iwd2 63439 100000","sdx6:*/ iwd2 47140 100000","sdx7:*/ iwd2 29028 100000","sdx8:*/ iwd2 9802 100000","sdy1:*/ ihd2 99518 100000","sdy2:*/ ihd2 95694 100000","sdy3:*/ ihd2 88192 100000","sdy4:*/ ihd2 77301 100000","sdy5:*/ ihd2 63439 100000","sdy6:*/ ihd2 47140 100000","sdy7:*/ ihd2 29028 100000","sdy8:*/ ihd2 9802 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc 0 sdx5","sx6:+- hc 0 sdx6","sx7:+- hc 0 sdx7","sx8:+- hc 0 sdx8","sx9:+- hc sdx8 0","sx10:+- hc sdx7 0","sx11:+- hc sdx6 0","sx12:+- hc sdx5 0","sx13:+- hc sdx4 0","sx14:+- hc sdx3 0","sx15:+- hc sdx2 0","sx16:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc 0 sdy5","sy6:+- vc 0 sdy6","sy7:+- vc 0 sdy7","sy8:+- vc 0 sdy8","sy9:+- vc sdy8 0","sy10:+- vc sdy7 0","sy11:+- vc sdy6 0","sy12:+- vc sdy5 0","sy13:+- vc sdy4 0","sy14:+- vc sdy3 0","sy15:+- vc sdy2 0","sy16:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy8 L x1 y7 L sx2 sy7 L x2 y6 L sx3 sy6 L x3 y5 L sx4 sy5 L x4 y4 L sx5 sy4 L x5 y3 L sx6 sy3 L x6 y2 L sx7 sy2 L x7 y1 L sx8 sy1 L hc t L sx9 sy1 L x8 y1 L sx10 sy2 L x9 y2 L sx11 sy3 L x10 y3 L sx12 sy4 L x11 y4 L sx13 sy5 L x12 y5 L sx14 sy6 L x13 y6 L sx15 sy7 L x14 y7 L sx16 sy8 L r vc L sx16 sy9 L x14 y8 L sx15 sy10 L x13 y9 L sx14 sy11 L x12 y10 L sx13 sy12 L x11 y11 L sx12 sy13 L x10 y12 L sx11 sy14 L x9 y13 L sx10 sy15 L x8 y14 L sx9 sy16 L hc b L sx8 sy16 L x7 y14 L sx7 sy15 L x6 y13 L sx6 sy14 L x5 y12 L sx5 sy13 L x4 y11 L sx4 sy12 L x3 y10 L sx3 sy11 L x2 y9 L sx2 sy10 L x1 y8 L sx1 sy9 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"bracketPair":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd2 cd4 L x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4 L x1 b A x1 x1 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 b A x1 x1 cd4 cd4 L l x1 A x1 x1 cd2 cd4 M x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"flowChartMerge":{"guides":["x2:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]}}; + +function geometryPaths(property, zoom) { + zoom = zoom || 1 + let geometry = property.geometry + let anchor = property.anchor ? [...property.anchor.map(s => s * zoom)] : property.anchor + if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { + return [] + } + let _anchor = [0, 0, anchor[2], anchor[3]] + if (geometry.name == 'custom') { + return getPaths(geometry.data.paths, true, _anchor, anchor, zoom) + } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { + let paths = [{ path: `M 0 0 L ${_anchor[2]} ${_anchor[3]}`, stroked: true, filled: true, w: -1, h: -1 }] + return getPaths(paths, false, _anchor, anchor) + } else { + let paths = calcPreGeometryPaths(geometry, _anchor) + return getPaths(paths, true, _anchor, anchor) + } +} + +function getPaths(paths, isEmu, anchor, real_anchor, zoom) { + let resultPaths = [] + for (let i = 0; i < paths.length; i++) { + let path = paths[i] + // console.log('path: ', path) + let scaleX = 1, scaleY = 1 + if (path.w > 0 && path.h > 0) { + if (path.w < 2000 && path.h < 2000) { + isEmu = false + } + let w = value2px(path.w, isEmu) + let h = value2px(path.h, isEmu) + scaleX = anchor[2] / w + scaleY = anchor[3] / h + } else if (zoom) { + scaleX = zoom + scaleY = zoom + } + let newPaths = [] + let split = path.path.replace(/\s+/g, ' ').trim().split(' ') + for (let j = 0; j < split.length; j++) { + switch (split[j]) { + case 'M': + case 'L': + newPaths.push(split[j]) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + break + case 'Q': + newPaths.push('Q') + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + break + case 'C': + newPaths.push('C') + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + newPaths.push(value2px(split[++j], isEmu)) + break + case 'Z': + newPaths.push('Z') + break + } + } + resultPaths.push({ + scaleX, + scaleY, + x: real_anchor[0], + y: real_anchor[1], + path: newPaths.join(' '), + stroked: path.stroked, + filled: path.filled + }) + } + return resultPaths +} + +function calcPreGeometryPaths(geometry, anchor) { + let pre = geometryMap[geometry.name] + if (!pre) { + console.log('未知形状:' + geometry.name) + return [] + } + // console.log(geometry.name) + let values = {} + let obj = { + x: value2emu(anchor[0]), + y: value2emu(anchor[1]), + width: value2emu(anchor[2]), + height: value2emu(anchor[3]), + centerX: value2emu(anchor[0] + anchor[2] / 2), + centerY: value2emu(anchor[1] + anchor[3] / 2), + maxX: value2emu(anchor[0] + anchor[2]), + maxY: value2emu(anchor[1] + anchor[3]), + values + } + if (pre.adjusts) { + for (let i = 0; i < pre.adjusts.length; i++) { + let adjust = pre.adjusts[i] + let idx = adjust.indexOf(':') + let name = adjust.substring(0, idx) + let fmla = adjust.substring(idx + 1) + let value = fmlaEvaluate(obj, fmla) + values[name] = value + } + } + if (geometry.avLst) { + for (let i = 0; i < geometry.avLst.length; i++) { + let adjust = geometry.avLst[i] + let idx = adjust.indexOf(':') + let name = adjust.substring(0, idx) + let fmla = adjust.substring(idx + 1) + let value = fmlaEvaluate(obj, fmla) + values[name] = value + } + } + if (pre.guides) { + for (let i = 0; i < pre.guides.length; i++) { + let adjust = pre.guides[i] + let idx = adjust.indexOf(':') + let name = adjust.substring(0, idx) + let fmla = adjust.substring(idx + 1) + let value = fmlaEvaluate(obj, fmla) + values[name] = value + } + } + let paths = pre.paths + let newPaths = [] + for (let i = 0; i < paths.length; i++) { + let path = { ...paths[i] } + let split = path.path.replace(/\s+/g, ' ').trim().split(' ') + let currentPoint = { x: obj.x, y: obj.y } + let newPath = [] + for (let j = 0; j < split.length; j++) { + switch (split[j]) { + case 'A': + let wr = pathEvaluate(obj, split[++j]) + let hr = pathEvaluate(obj, split[++j]) + let stAng = pathEvaluate(obj, split[++j]) + let swAng = pathEvaluate(obj, split[++j]) + let _paths = arcToBezierCurve(currentPoint, wr, hr, stAng, swAng) + // console.log('A: ', _paths) + let p = 0 + if (_paths[0] == 'M' && newPath.length > 0 && newPath[newPath.length - 1] != 'Z' && + valueEquals(newPath[newPath.length - 2], _paths[1]) && valueEquals(newPath[newPath.length - 1], _paths[2])) { + p = 3 + } + for (; p < _paths.length; p++) { + newPath.push(_paths[p]) + } + currentPoint.x = _paths[_paths.length - 2] + currentPoint.y = _paths[_paths.length - 1] + break + case 'M': + case 'L': + newPath.push(split[j]) + currentPoint.x = pathEvaluate(obj, split[++j]) + currentPoint.y = pathEvaluate(obj, split[++j]) + newPath.push(currentPoint.x) + newPath.push(currentPoint.y) + break + case 'Q': + newPath.push(split[j]) + newPath.push(pathEvaluate(obj, split[++j])) + newPath.push(pathEvaluate(obj, split[++j])) + currentPoint.x = pathEvaluate(obj, split[++j]) + currentPoint.y = pathEvaluate(obj, split[++j]) + newPath.push(currentPoint.x) + newPath.push(currentPoint.y) + break + case 'C': + newPath.push(split[j]) + newPath.push(pathEvaluate(obj, split[++j])) + newPath.push(pathEvaluate(obj, split[++j])) + newPath.push(pathEvaluate(obj, split[++j])) + newPath.push(pathEvaluate(obj, split[++j])) + currentPoint.x = pathEvaluate(obj, split[++j]) + currentPoint.y = pathEvaluate(obj, split[++j]) + newPath.push(currentPoint.x) + newPath.push(currentPoint.y) + break + case 'Z': + newPath.push(split[j]) + break + } + } + path.path = newPath.join(' ') + newPaths.push(path) + } + return newPaths +} + +function pathEvaluate(obj, value) { + if (obj.values && obj.values[value] != null) { + return obj.values[value] + } + let ss = Math.min(obj.width, obj.height) + switch (value) { + case 'l': + return obj.x + case 't': + return obj.y + case 'b': + return obj.maxY + case 'r': + return obj.maxX + case 'hc': + return obj.centerX + case 'vc': + return obj.centerY + case '3cd4': + return 1.62E7 + case '3cd8': + return 8100000 + case '5cd8': + return 1.35E7 + case '7cd8': + return 1.89E7 + case 'cd2': + return 1.08E7 + case 'cd4': + return 5400000 + case 'cd8': + return 2700000 + case 'ss': + return ss + case 'ssd2': + return ss / 2 + case 'ssd4': + return ss / 4 + case 'ssd6': + return ss / 6 + case 'ssd8': + return ss / 8 + case 'ssd16': + return ss / 16 + case 'ssd32': + return ss / 32 + case 'ls': + return Math.max(obj.width, obj.height) + case 'w': + return obj.width + case 'wd2': + return obj.width / 2 + case 'wd3': + return obj.width / 3 + case 'wd4': + return obj.width / 4 + case 'wd5': + return obj.width / 5 + case 'wd6': + return obj.width / 6 + case 'wd8': + return obj.width / 8 + case 'wd10': + return obj.width / 10 + case 'wd32': + return obj.width / 32 + case 'h': + return obj.height + case 'hd2': + return obj.height / 2 + case 'hd3': + return obj.height / 3 + case 'hd4': + return obj.height / 4 + case 'hd5': + return obj.height / 5 + case 'hd6': + return obj.height / 6 + case 'hd7': + return obj.height / 7 + case 'hd8': + return obj.height / 8 + default: + if (/^(-)?(\d+)(\.)?(\d+)?$/.test(value)) { + return +value + } else { + console.log('未知pathEval: ' + value) + return 0 + } + } +} + +function fmlaEvaluate(obj, fmla) { + let split = fmla.replace(/\s+/g, ' ').trim().split(' ') + let op = split[0] + let x = split.length > 1 ? pathEvaluate(obj, split[1]) : 0 + let y = split.length > 2 ? pathEvaluate(obj, split[2]) : 0 + let z = split.length > 3 ? pathEvaluate(obj, split[3]) : 0 + switch (op) { + case 'abs': + return Math.abs(x) + case '+/': + case 'adddiv': + return z == 0 ? 0 : (x + y) / z + case '+-': + case 'addsub': + return x + y - z + case 'at2': + return (Math.atan2(y, x) * 180 / Math.PI) * 60000 + case 'cos': + return x * Math.cos(y / 60000 / 180 * Math.PI) + case 'cat2': + return x * Math.cos(Math.atan2(z, y)) + case '?:': + case 'ifelse': + return x > 0 ? y : z + case 'val': + return x + case 'max': + return Math.max(x, y) + case 'min': + return Math.min(x, y) + case 'mod': + return Math.sqrt(x * x + y * y + z * z) + case '*/': + case 'muldiv': + return z == 0 ? 0 : x * y / z + case 'pin': + return Math.max(x, Math.min(y, z)) + case 'sat2': + return x * Math.sin(Math.atan2(z, y)) + case 'sin': + return x * Math.sin(y / 60000 / 180 * Math.PI) + case 'sqrt': + return Math.sqrt(x) + case 'tan': + return x * Math.tan(y / 60000 / 180 * Math.PI) + default: + console.log('未知op: ' + op, fmla) + return 0 + } +} + +function arcToBezierCurve(pt, wr, hr, stAng, swAng) { + let rx = wr + let ry = hr + let ooStart = stAng / 60000 + let ooExtent = swAng / 60000 + let start = convertOoxml2Angle(ooStart, rx, ry) + let extent = convertOoxml2Angle(ooStart + ooExtent, rx, ry) - start + let radStart = ooStart / 180 * Math.PI + let invStart = Math.atan2(rx * Math.sin(radStart), ry * Math.cos(radStart)) + let x0 = pt.x - rx * Math.cos(invStart) - rx + let y0 = pt.y - ry * Math.sin(invStart) - ry + let arc = { x: x0, y: y0, width: rx * 2, height: ry * 2, start: start, extent: extent, type: 0 } + return arcToBezierCurvePaths(arc) +} + +function arcToBezierCurvePaths(a) { + let x, y, w, h, angStRad, increment, cv + let arcSegs = 0, lineSegs = 0 + w = a.width / 2 + h = a.height / 2 + x = a.x + w + y = a.y + h + angStRad = -(a.start / 180 * Math.PI) + let ext = -a.extent + if (ext >= 360 || ext <= -360) { + arcSegs = 4 + increment = Math.PI / 2 + cv = 0.5522847498307933 + if (ext < 0) { + increment = -increment + cv = -cv + } + } else { + arcSegs = Math.ceil(Math.abs(ext) / 90) + increment = (ext / arcSegs) / 180 * Math.PI + let _increment = increment / 2 + cv = 4 / 3 * Math.sin(_increment) / (1 + Math.cos(_increment)) + if (cv == 0) { + arcSegs = 0 + } + } + lineSegs = a.type + if (w < 0 || h < 0) { + arcSegs = lineSegs = -1 + } + let paths = [] + let coords = [0, 0, 0, 0, 0, 0] + for (let index = 0; index <= arcSegs + lineSegs; index++) { + let angle = angStRad + if (index == 0) { + coords[0] = x + Math.cos(angle) * w + coords[1] = y + Math.sin(angle) * h + paths.push('M') + paths.push(coords[0]) + paths.push(coords[1]) + continue + } + if (index > arcSegs) { + if (index == arcSegs + lineSegs) { + paths.push('Z') + continue + } + coords[0] = x + coords[1] = y + paths.push('L') + paths.push(coords[0]) + paths.push(coords[1]) + continue + } + angle += increment * (index - 1) + let relx = Math.cos(angle) + let rely = Math.sin(angle) + coords[0] = x + (relx - cv * rely) * w + coords[1] = y + (rely + cv * relx) * h + angle += increment + relx = Math.cos(angle) + rely = Math.sin(angle) + coords[2] = x + (relx + cv * rely) * w + coords[3] = y + (rely - cv * relx) * h + coords[4] = x + relx * w + coords[5] = y + rely * h + paths.push('C') + paths.push(coords[0]) + paths.push(coords[1]) + paths.push(coords[2]) + paths.push(coords[3]) + paths.push(coords[4]) + paths.push(coords[5]) + } + return paths +} + +function convertOoxml2Angle(ooAngle, width, height) { + let aspect = height / width + let awtAngle = -ooAngle + let awtAngle2 = awtAngle % 360 + let awtAngle3 = awtAngle - awtAngle2 + switch (parseInt(awtAngle2 / 90)) { + case -3: + awtAngle3 -= 360 + awtAngle2 += 360 + break + case -2: + case -1: + awtAngle3 -= 180 + awtAngle2 += 180 + case 0: + break + default: + break + case 1: + case 2: + awtAngle3 += 180 + awtAngle2 -= 180 + break + case 3: + awtAngle3 += 360 + awtAngle2 -= 360 + } + awtAngle = (Math.atan2(Math.tan(awtAngle2 / 180 * Math.PI), aspect)) * 180 / Math.PI + awtAngle3 + return awtAngle +} + +function value2px(v, isEmu) { + if (isEmu) { + return +v / 12700 + } else { + return +v + } +} + +function value2emu(v) { + return +v * 12700 +} + +function valueEquals(v1, v2) { + if (v1 == v2) { + return true + } + if (v1 != null && v2 == null || v1 == null && v2 != null) { + return false + } + if (v1 > 1000 && Math.abs(v1 - v2) < 0.001) { + return true + } + let f1 = v1.toFixed(6) + let f2 = v2.toFixed(6) + if (f1 == f2) { + return true + } + if (f1 == '0.000000' && f2 == '-0.000000' || f1 == '-0.000000' && f2 == '0.000000') { + return true + } + return false +} + +export { geometryPaths } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js new file mode 100644 index 0000000..54e8d72 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js @@ -0,0 +1,1328 @@ +/* eslint-disable no-unused-vars */ +/* eslint-disable no-self-assign */ +import { geometryPaths } from './geometry.js' +import { drawChart } from './chart.js' + +function Ppt2Canvas(_canvas, imageCrossOrigin) { + var canvas = (typeof _canvas == 'string') ? document.getElementById(_canvas) : _canvas + var ctx = canvas.getContext('2d') + var pptx = null + var page = null + var idMap = {} + var imageCache = {} + var pageIndex = 0 + var templateHandle = null + + this.drawPptx = async (pptxObj, pageIdx) => { + idMap = {} + imageCache = {} + pptx = pptxObj + pageIndex = pageIdx + page = pptxObj.pages[pageIdx] + canvas.width = canvas.width + canvas.height = canvas.height + ctx.scaleX = canvas.width / pptxObj.width + ctx.scaleY = canvas.height / pptxObj.height + ctx.scale(ctx.scaleX, ctx.scaleY) + ctx.interior = ctx._interior = null + let placeholder = {} + let slideMasterIdx = page.extInfo.slideMasterIdx + if (slideMasterIdx != null && pptxObj.slideMasters) { + let slideMaster = pptxObj.slideMasters[slideMasterIdx] + let slideLayoutIdx = page.extInfo.slideLayoutIdx + let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null + await drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) + await drawSlideMaster(slideMaster, slideLayout, placeholder) + if (slideLayout) { + await drawSlideLayout(slideLayout, placeholder) + } + } else { + await drawBackground(page.extInfo.background) + } + if (!page.children) { + return + } + recursion(page.children, obj => { + idMap[obj.id] = obj + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + // 继承母版占位符 + let element_property = obj.extInfo.property + let placeholder_property = placeholder[element_property.placeholder.type] || {} + for (let k in placeholder_property) { + if (element_property[k] == null) { + element_property[k] = placeholder_property[k] + } + } + } + }) + for (let i = 0; i < page.children.length; i++) { + await drawElement(page.children[i]) + } + recursion(page.children, obj => { + idMap[obj.id] = obj + }) + } + + this.getCanvas = () => { + return canvas + } + + this.resetSize = (width, height) => { + canvas.width = width * 2 + canvas.height = height * 2 + canvas.style.width = width + 'px' + canvas.style.height = height + 'px' + if (pptx) { + this.drawPptx(pptx, pageIndex) + } + } + + async function drawElement(obj) { + ctx.fillStyle = 'transparent' + ctx.strokeStyle = 'transparent' + if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { + // console.log('ignore element:', obj) + return + } + if (obj.type == 'text' || obj.type == 'freeform') { + await drawText(obj) + } else if (obj.type == 'image') { + await drawImage(obj) + } else if (obj.type == 'diagram') { + await drawDiagram(obj) + } else if (obj.type == 'container') { + await drawContainer(obj) + } else if (obj.type == 'table') { + await drawTable(obj) + } else if (obj.type == 'connector') { + await drawConnector(obj) + } else if (obj.type == 'graphicFrame') { + await drawGraphicFrame(obj) + } + } + + async function drawText(obj) { + let property = obj.extInfo.property + let geometryName = (property.geometry || {}).name || 'rect' + ctx.save() + shapeHandle(property) + let marginTop = property.strokeStyle ? (property.strokeStyle.lineWidth || 1) : 0 + if (geometryName == 'tableColumn') { + await drawTableColumn(property) + } else { + await drawGeometry(property) + } + let anchor = property.anchor + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + let x = ctx.groupFlipX || 1 + let y = ctx.groupFlipY || 1 + if (property.flipHorizontal) { + x *= -1 + } + if (property.flipVertical) { + y *= -1 + } + if (y == -1) { + if (x == 1) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + } + } else if (x == -1) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + } + if (templateHandle) { + await templateHandle('text', obj, ctx) + } + if (obj.children) { + let textInsets = property.textInsets || [0, 0, 0, 0] + let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 + let verticalAlignment = property.textVerticalAlignment + if (!isVertical && (verticalAlignment == 'MIDDLE' || verticalAlignment == 'BOTTOM')) { + let totalTextHeight = calcTextHeight(obj) + if (totalTextHeight < property.anchor[3]) { + if (verticalAlignment == 'MIDDLE') { + marginTop += (property.anchor[3] - totalTextHeight - textInsets[0] - textInsets[2]) / 2 + textInsets[0] + } else if (verticalAlignment == 'BOTTOM') { + marginTop += (property.anchor[3] - totalTextHeight - textInsets[2]) + } + } + } else { + marginTop += textInsets[0] + } + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + if (isVertical) { + await drawTextP(obj, p, isVertical, 0, i) + } else { + marginTop += await drawTextP(obj, p, isVertical, marginTop, i) + } + } + } + ctx.restore() + } + + function calcTextHeight(obj) { + let totalTextHeight = 0 + let wordWrap = obj.extInfo.property.textWordWrap ?? true + let textInsets = obj.extInfo.property.textInsets || [0, 0, 0, 0] + let wInset = textInsets[1] + textInsets[3] + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) + let maxFontSize = 0 + let underlined = false + let totalTextWidth = 0 + for (let j = 0; j < p.children.length; j++) { + let r_property = p.children[j].extInfo.property + let fontSize = r_property.fontSize || 16 + let text = p.children[j].text + if (text == '\n') { + totalTextHeight += lineSpacing * fontSize + continue + } + if (fontSize > maxFontSize) { + maxFontSize = fontSize + } + if (r_property.underlined) { + underlined = true + } + let fonts = [] + if (r_property.bold) { + fonts.push('bold') + } + if (r_property.italic) { + fonts.push('italic') + } + fonts.push(fontSize + 'px') + fonts.push('"' + (r_property.fontFamily || '等线') + '"') + ctx.font = fonts.join(' ') + let lines = text.split('\n') + let maxTextWidth = 0 + for (let s = 0; s < lines.length; s++) { + let width = ctx.measureText(lines[s]).width + if (width > maxTextWidth) { + maxTextWidth = width + } + } + totalTextWidth += maxTextWidth + if (lines.length > 1) { + totalTextHeight += (lines.length - 1) * lineSpacing * fontSize + } + } + if (wordWrap) { + let lineNum = parseInt((totalTextWidth - 1) / (obj.extInfo.property.anchor[2] - wInset)) + 1 + totalTextHeight += lineNum * lineSpacing * maxFontSize + } else { + totalTextHeight += lineSpacing * maxFontSize + } + if (underlined) { + totalTextHeight += 1 + } + } + return totalTextHeight + } + + async function drawTextP(textObj, p, isVertical, marginTop, pIdx) { + if (!p.children) { + return + } + let fontList = [] + let underlined = false + let totalTextWidth = 0 + let anchor = textObj.extInfo.property.anchor + let wordWrap = textObj.extInfo.property.textWordWrap ?? true + for (let i = 0; i < p.children.length; i++) { + let r = p.children[i] + let property = r.extInfo.property + let fontSize = property.fontSize || 16 + let fonts = [] + if (property.bold) { + fonts.push('bold') + } + if (property.italic) { + fonts.push('italic') + } + if (property.slideNum) { + r.text = (pageIndex + 1) + '' + } + fonts.push(fontSize + 'px') + fonts.push('"' + (property.fontFamily || '等线') + '"') + let font = fonts.join(' ') + fontList.push(font) + ctx.font = font + if (isVertical) { + if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { + if (fontSize > totalTextWidth) { + totalTextWidth = fontSize + } + } else if (r.text.length > 0) { + let width = ctx.measureText(r.text[0]).width + if (width > totalTextWidth) { + totalTextWidth = width + } + } + } else { + let lines = r.text.split('\n') + let maxTextWidth = 0 + for (let s = 0; s < lines.length; s++) { + let width = ctx.measureText(lines[s]).width + if (width > maxTextWidth) { + maxTextWidth = width + } + } + totalTextWidth += maxTextWidth + } + if (property.underlined) { + underlined = true + } + } + if (wordWrap) { + totalTextWidth = Math.min(totalTextWidth, anchor[2]) + } + let textAlign = p.extInfo.property.textAlign + let verticalAlignment = textObj.extInfo.property.textVerticalAlignment + let textInsets = textObj.extInfo.property.textInsets || [0, 0, 0, 0] + let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) + let x = anchor[0] + let y = anchor[1] + (marginTop || 0) + let endX = anchor[0] + anchor[2] - textInsets[3] + ctx.textAlign = 'left' + ctx.textBaseline = 'top' + if (textAlign == 'CENTER') { + x = x + (anchor[2] - totalTextWidth - textInsets[1] - textInsets[3]) / 2 + textInsets[1] + } else if (textAlign == 'RIGHT') { + x = x + anchor[2] - textInsets[3] - totalTextWidth + } else { + x = x + textInsets[1] + } + const _x = x + const _y = y + let lastWord = null + let maxFontSize = 0 + for (let i = 0; i < p.children.length; i++) { + let r = p.children[i] + let property = r.extInfo.property + let fontSize = property.fontSize || 16 + let drawString = (s, x, y) => { + doShadow(ctx, property.shadow) + ctx.translate(x, y) + ctx.fillText(s, 0, 0) + ctx.translate(-x, -y) + } + let fillStyle = await toPaint(property.fontColor, anchor) + ctx.fillStyle = fillStyle + if (property.line && (property.fontColor == null || property.fontColor.type == 'noFill')) { + drawString = (s, x, y) => { + doShadow(ctx, property.shadow) + ctx.translate(x, y) + ctx.strokeText(s, 0, 0) + ctx.translate(-x, -y) + } + ctx.strokeStyle = await toPaint(property.line.paint, anchor) + } + ctx.font = fontList[i] + if (fontSize > maxFontSize) { + maxFontSize = fontSize + } + if (r.text == '\n') { + y += lineSpacing * fontSize + x = _x + continue + } + if (isVertical) { + // 竖版 + x = x + fontSize * pIdx + if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { + // 数字英文竖着的时候需要旋转90°方式呈现 + let textWidth = ctx.measureText(r.text).width + let fontSize = property.fontSize || 16 + ctx.save() + ctx.translate(x, y + fontSize) + ctx.rotate(90 * Math.PI / 180) + ctx.translate(-x, -y - fontSize) + drawString(r.text, x - fontSize, y) + ctx.restore() + y += textWidth + } else { + for (let j = 0; j < r.text.length; j++) { + let text = r.text[j] + drawString(text, x, y) + y += fontSize + } + } + if (property.underlined) { + let lineX = x + let lineY = _y + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX, lineY + (y - _y)) + ctx.closePath() + ctx.stroke() + } + } else if (wordWrap) { + // 横版-自动换行 + let texts = splitWords(r.text) + let drawLine = (textWidth) => { + if (property.underlined) { + let lineX = _x + let lineY = y + if (verticalAlignment == 'MIDDLE') { + lineY = lineY + fontSize / 2 + 1 + } else if (verticalAlignment == 'BOTTOM') { + lineY = lineY + 1 + } else { + lineY = lineY + fontSize + 1 + } + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX + textWidth, lineY) + ctx.closePath() + ctx.stroke() + } + } + for (let j = 0; j < texts.length; j++) { + let item = texts[j] + if (item.text == '\n') { + x = _x + y += lineSpacing * fontSize + lastWord = null + continue + } + if (item.word && lastWord != null && !lastWord) { + let textWidth = ctx.measureText(item.text).width + if (x + textWidth > endX + fontSize / 4) { + drawLine(x - _x) + x = _x + y += lineSpacing * fontSize + } + } + for (let s = 0; s < item.text.length; s++) { + let text = item.text[s] + let textWidth = ctx.measureText(text).width + if (x + textWidth > endX + fontSize / 4 && !isSymbol(text)) { + drawLine(x - _x) + x = _x + y += lineSpacing * fontSize + } + let ty = y + if (verticalAlignment == 'MIDDLE') { + ctx.textBaseline = 'middle' + ty = ty + (lineSpacing * fontSize) / 2 + } else if (verticalAlignment == 'BOTTOM') { + ctx.textBaseline = 'bottom' + ty = ty + (lineSpacing * fontSize) + } else { + ctx.textBaseline = 'top' + } + drawString(text, x, ty) + x += textWidth + } + lastWord = item.word + } + if (i == p.children.length - 1) { + drawLine(x - _x) + } + } else { + // 横版-不自动换行 + let lines = r.text.split('\n') + for (let s = 0; s < lines.length; s++) { + if (s != 0) { + x = _x + y += lineSpacing * fontSize + } + let ty = y + if (verticalAlignment == 'MIDDLE') { + ctx.textBaseline = 'middle' + ty = ty + (lineSpacing * fontSize) / 2 + } else if (verticalAlignment == 'BOTTOM') { + ctx.textBaseline = 'bottom' + ty = ty + (lineSpacing * fontSize) + } else { + ctx.textBaseline = 'top' + } + drawString(lines[s], x, ty) + let textWidth = ctx.measureText(lines[s]).width + if (property.underlined) { + let lineX = x + let lineY = y + if (verticalAlignment == 'MIDDLE') { + lineY = lineY + fontSize / 2 + 1 + } else if (verticalAlignment == 'BOTTOM') { + lineY = lineY + 1 + } else { + lineY = lineY + fontSize + 1 + } + ctx.lineWidth = 1 + ctx.strokeStyle = fillStyle + ctx.beginPath() + ctx.moveTo(lineX, lineY) + ctx.lineTo(lineX + textWidth, lineY) + ctx.closePath() + ctx.stroke() + } + x += textWidth + } + } + } + return (y - _y) + (underlined && !isVertical ? 1 : 0) + lineSpacing * maxFontSize + } + + async function drawImage(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + if (property.fillStyle && property.fillStyle.texture) { + property.fillStyle.texture.imageData = property.image + // 图片自带拉伸 + property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] + } else { + property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } + } + if (!property.geometry) { + property.geometry = { name: 'rect' } + } + await drawGeometry(property) + if (templateHandle) { + await templateHandle('image', obj, ctx) + } + ctx.restore() + } + + async function drawTableColumn(property) { + let anchor = property.anchor + let x = anchor[0] - 1 + let endX = anchor[0] + anchor[2] + 1 + let y = anchor[1] - 1 + let endY = anchor[1] + anchor[3] + 1 + let borders = property.borders // top/left/bottom/right + ctx.beginPath() + ctx.moveTo(x, y) + let top = borders[0] + ctx.strokeStyle = toColor({ color: top.color }, 'white') + ctx.lineWidth = top.lineWidth + ctx.lineTo(endX, y) + let right = borders[3] + ctx.strokeStyle = toColor({ color: right.color }, 'white') + ctx.lineWidth = right.lineWidth + ctx.lineTo(endX, endY) + let bottom = borders[2] + ctx.strokeStyle = toColor({ color: bottom.color }, 'white') + ctx.lineWidth = bottom.lineWidth + ctx.lineTo(x, endY) + let left = borders[1] + ctx.strokeStyle = toColor({ color: left.color }, 'white') + ctx.lineWidth = left.lineWidth + ctx.lineTo(x, anchor[1]) + ctx.closePath() + ctx.fillStyle = await toPaint(property.fillStyle, property.anchor) + ctx.fill() + ctx.stroke() + } + + async function drawDiagram(obj) { + let property = obj.extInfo.property + ctx.save() + ctx.translate(property.anchor[0], property.anchor[1]) + if (templateHandle) { + await templateHandle('diagram', obj, ctx) + } + for (let i = 0; i < obj.children.length; i++) { + await drawElement(obj.children[i]) + } + ctx.translate(-property.anchor[0], -property.anchor[1]) + ctx.restore() + } + + async function drawContainer(obj) { + let property = obj.extInfo.property + if (property.realType == 'Group') { + ctx.save() + let _groupFlipX = ctx.groupFlipX + let _groupFlipY = ctx.groupFlipY + let _groupRotation = ctx.groupRotation + if (templateHandle) { + await templateHandle('container', obj, ctx) + } + shapeHandle(property) + let parentGroupFillStyle = ctx.groupFillStyle + let groupFillStyle = property.groupFillStyle + if (groupFillStyle) { + groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) + groupFillStyle.groupAnchor = property.anchor + if (parentGroupFillStyle) { + groupFillStyle.parentGroupFillStyle = parentGroupFillStyle + } + } + ctx.groupFillStyle = groupFillStyle + let copyChildren = JSON.parse(JSON.stringify(obj.children)) + recursionGroupChildren(copyChildren, c => { + if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { + let anchor = c.extInfo.property.anchor + anchor[0] *= ctx.interior.scaleX + anchor[1] *= ctx.interior.scaleY + anchor[2] *= ctx.interior.scaleX + anchor[3] *= ctx.interior.scaleY + } + }) + for (let i = 0; i < copyChildren.length; i++) { + await drawElement(copyChildren[i]) + } + ctx.interior = ctx._interior + ctx.groupFlipX = _groupFlipX + ctx.groupFlipY = _groupFlipY + ctx.groupRotation = _groupRotation + ctx.restore() + } else { + for (let i = 0; i < obj.children.length; i++) { + await drawElement(obj.children[i]) + } + } + } + + function recursionGroupChildren(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.extInfo && c.extInfo.property.realType == 'Group') { + continue + } + if (c.children && c.children.length > 0) { + recursionGroupChildren(c.children, fn) + } + } + } + + async function drawConnector(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + await drawGeometry(property) + if (templateHandle) { + await templateHandle('connector', obj, ctx) + } + ctx.restore() + } + + async function drawGraphicFrame(obj) { + let property = obj.extInfo.property + ctx.save() + shapeHandle(property) + if (templateHandle) { + await templateHandle('graphicFrame', obj, ctx) + } + if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { + await drawChart(property.chart, property.anchor, canvas, ctx) + } + ctx.restore() + } + + async function drawTable(obj) { + let property = obj.extInfo.property + for (let i = 0; i < obj.children.length; i++) { + let row = obj.children[i] + await drawTableRow(obj, row) + } + } + + async function drawTableRow(table, row) { + let property = row.extInfo.property + for (let i = 0; i < row.children.length; i++) { + let column = row.children[i] + await drawText(column) + } + } + + async function drawGeometry(property) { + let geometry = property.geometry + let anchor = property.anchor + if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { + return + } + ctx.save() + ctx.translate(anchor[0], anchor[1]) + let paths = geometryPaths(property) + let _anchor = [0, 0, anchor[2], anchor[3]] + if (geometry.name == 'custom') { + await drawPaths(paths, property, _anchor, anchor) + } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { + await drawPaths(paths, property, _anchor, anchor) + } else { + await drawPaths(paths, property, _anchor, anchor) + } + ctx.translate(-anchor[0], -anchor[1]) + ctx.restore() + } + + async function drawPaths(paths, property, anchor, real_anchor) { + for (let i = 0; i < paths.length; i++) { + let path = paths[i] + // console.log('path: ', path) + ctx.save() + let scaleX = path.scaleX + let scaleY = path.scaleY + ctx.scale(scaleX, scaleY) + let _anchor = [anchor[0], anchor[1], anchor[2], anchor[3]] + if (scaleX != 1 || scaleY != 1) { + _anchor[0] = _anchor[0] / scaleX + _anchor[1] = _anchor[1] / scaleY + _anchor[2] = _anchor[2] / scaleX + _anchor[3] = _anchor[3] / scaleY + } + ctx.beginPath() + let split = path.path.replace(/\s+/g, ' ').trim().split(' ') + for (let j = 0; j < split.length; j++) { + switch (split[j]) { + case 'M': + ctx.moveTo(split[++j], split[++j]) + break + case 'L': + ctx.lineTo(split[++j], split[++j]) + break + case 'Q': + ctx.quadraticCurveTo(split[++j], split[++j], split[++j], split[++j]) + break + case 'C': + ctx.bezierCurveTo(split[++j], split[++j], split[++j], split[++j], split[++j], split[++j]) + break + case 'Z': + ctx.closePath() + break + } + } + let strokeStyle = null + if (property.strokeStyle) { + ctx.lineWidth = (property.strokeStyle.lineWidth || 1) / scaleY + let lineCap = property.strokeStyle.lineCap + if (!lineCap || lineCap == 'FLAT') { + lineCap = 'butt' + } + ctx.lineCap = lineCap.toLowerCase() + strokeStyle = await toPaint(property.strokeStyle.paint, _anchor) + } + doShadow(ctx, property.shadow) + if (path.stroked && strokeStyle) { + ctx.strokeStyle = strokeStyle + } else { + ctx.strokeStyle = 'transparent' + } + ctx.stroke() + ctx.scale(1 / scaleX, 1 / scaleY) + let fillStyle = await toPaint(property.fillStyle, anchor) + if (path.filled) { + ctx.fillStyle = fillStyle + } else { + ctx.fillStyle = 'transparent' + } + if (property.fillStyle && property.fillStyle.type == 'bgFill') { + let rotation = (property.rotation || 0) + (ctx.groupRotation || 0) + if (rotation) { + ctx.translate(real_anchor[2] / 2, real_anchor[3] / 2) + ctx.rotate(-rotation * Math.PI / 180) + ctx.translate(-real_anchor[2] / 2, -real_anchor[3] / 2) + } + let tx = 0, ty = 0 + if (ctx.interior) { + tx = -ctx.interior.tx - real_anchor[0] + ty = -ctx.interior.ty - real_anchor[1] + } else { + tx = -real_anchor[0] + ty = -real_anchor[1] + } + ctx.translate(tx, ty) + ctx.fill() + ctx.translate(-tx, -ty) + } else { + ctx.fill() + } + ctx.restore() + } + } + + function shapeHandle(property) { + let anchor = property.anchor + if (!anchor) { + return + } + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + if (property.rotation) { + // 旋转 + ctx.translate(cx, cy) + ctx.rotate(property.rotation * Math.PI / 180) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation + } + } + if (property.flipVertical) { + ctx.translate(cx, cy) + ctx.scale(1, -1) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupFlipY = -(ctx.groupFlipY || 1) + } + } + if (property.flipHorizontal) { + ctx.translate(cx, cy) + ctx.scale(-1, 1) + ctx.translate(-cx, -cy) + if (property.realType == 'Group') { + ctx.groupFlipX = -(ctx.groupFlipX || 1) + } + } + // 嵌套容器 Group + let interior = property.interiorAnchor + if (interior && interior.length > 0) { + /* + // 缩放 + let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] + let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] + ctx.scale(scaleX, scaleY) + ctx.translate(anchor[0] / scaleX - interior[0], anchor[1] / scaleY - interior[1]) + */ + let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] + let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] + let tx = anchor[0] - interior[0] * scaleX + let ty = anchor[1] - interior[1] * scaleY + ctx.translate(tx, ty) + ctx._interior = ctx.interior + ctx.interior = { scaleX, scaleY, tx, ty } + } else if (property.realType == 'Group') { + ctx._interior = ctx.interior + ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } + } + } + + async function drawBackground(background) { + if (!background) { + ctx.bgFillStyle = null + return + } + ctx.fillStyle = await toPaint(background.fillStyle, background.anchor, true) + ctx.fillRect(background.anchor[0], background.anchor[1], background.anchor[2], background.anchor[3]) + ctx.bgFillStyle = ctx.fillStyle + } + + async function drawSlideMaster(slideMaster, slideLayout, placeholder) { + recursion(slideMaster.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + if (slideLayout && slideLayout.noMaster) { + return + } + for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { + await drawElement(slideMaster.children[i]) + } + } + + async function drawSlideLayout(slideLayout, placeholder) { + recursion(slideLayout.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { + await drawElement(slideLayout.children[i]) + } + } + + function recursion(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.children && c.children.length > 0) { + recursion(c.children, fn) + } + } + } + + function doShadow(ctx, shadow) { + if (!shadow) { + return + } + ctx.shadowBlur = shadow.blur || 0 + ctx.shadowColor = toColor(shadow.fillStyle.color) + if (shadow.distance) { + let radians = (shadow.angle || 0) * Math.PI / 180 + let x = 0, y = 0, r = shadow.distance * 2 + ctx.shadowOffsetX = x + r * Math.cos(radians) + ctx.shadowOffsetY = y + r * Math.sin(radians) + } + } + + function toPaint(paint, anchor, isBackground, defaultColor) { + return new Promise((resolve, reject) => { + if (!paint) { + resolve(defaultColor || 'transparent') + } else if (paint.type == 'noFill') { + // 无填充 + resolve('transparent') + } else if (paint.type == 'color') { + // 颜色 + resolve(toColor(paint.color, defaultColor)) + } else if (paint.type == 'bgFill') { + // 背景填充 + resolve(ctx.bgFillStyle || defaultColor || 'transparent') + } else if (paint.type == 'groupFill') { + // 组合背景 + let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle + if (groupFillStyle) { + toPaint(groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { + resolve(res) + }) + } else { + resolve(defaultColor || 'transparent') + } + } else if (paint.type == 'gradient') { + // 渐变 + let gradient = paint.gradient + let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] + let centerX = x + width / 2 + let centerY = y + height / 2 + let gradientObj + // linear,circular,rectangular,shape + if (gradient.gradientType == 'circular') { + // 射线 + let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) + let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 + let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 + gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) + } else { + // 线性 + let startX = x + let startY = centerY + let endX = x + width + let endY = centerY + if (gradient.angle) { + let radians = gradient.angle * Math.PI / 180 + let midX = (startX + endX) / 2 + let midY = (startY + endY) / 2 + let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) + let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) + let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) + let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) + startX = newStartX + startY = newStartY + endX = newEndX + endY = newEndY + } + gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) + } + for (let i = 0; i < gradient.colors.length; i++) { + let color = gradient.colors[i] + gradientObj.addColorStop(gradient.fractions[i], toColor(color)) + } + resolve(gradientObj) + } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { + resolve('transparent') + } else if (paint.type == 'texture') { + // 图片或纹理 + let texture = paint.texture + let anonymous = texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst + loadImage(texture.imageData, anonymous).then(img => { + if (img) { + let pat = createTexturePattern(img, texture, anchor, isBackground) + resolve(pat) + } else { + resolve('transparent') + } + }) + } else if (paint.type == 'pattern') { + // 图案 + let pattern = paint.pattern + // let prst = pattern.prst + let fgColor = pattern.fgColor.realColor + let bgColor = pattern.bgColor.realColor + let width = anchor[2], height = anchor[3] + let imgCanvas = document.createElement('canvas') + imgCanvas.width = width + imgCanvas.height = height + let imgCtx = imgCanvas.getContext('2d') + imgCtx.imageSmoothingEnabled = true + imgCtx.imageSmoothingQuality = 'high' + let imgData = imgCtx.createImageData(width, height) + let line = 0 + for (let i = 0; i < imgData.data.length; i += 4) { + if (++line % 16 == 0) { + // 前景 + imgData.data[i + 0] = (fgColor >> 16) & 255 + imgData.data[i + 1] = (fgColor >> 8) & 255 + imgData.data[i + 2] = (fgColor >> 0) & 255 + imgData.data[i + 3] = (fgColor >> 24) & 255 + } else { + // 背景 + imgData.data[i + 0] = (bgColor >> 16) & 255 + imgData.data[i + 1] = (bgColor >> 8) & 255 + imgData.data[i + 2] = (bgColor >> 0) & 255 + imgData.data[i + 3] = (bgColor >> 24) & 255 + } + if (i % 400 == 0) { + line += 2 + } + } + imgCtx.putImageData(imgData, 0, 0) + let imgSrc = imgCanvas.toDataURL() + let image = new Image() + image.src = imgSrc + image.onload = async function() { + resolve(ctx.createPattern(image, 'no-repeat')) + } + } + }) + } + + function createTexturePattern(img, texture, anchor, isBackground) { + let width = anchor[2] + let height = anchor[3] + let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' + if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { + return ctx.createPattern(img, mode) + } + if (texture.alignment || !texture.stretch) { + width = img.width + height = img.height + } + let patternCanvas = document.createElement('canvas') + patternCanvas.width = Math.max(1, width) + patternCanvas.height = Math.max(1, height) + let patternCtx = patternCanvas.getContext('2d') + patternCtx.imageSmoothingEnabled = true + patternCtx.imageSmoothingQuality = 'high' + if (texture.alpha >= 0 && texture.alpha < 100000) { + patternCtx.globalAlpha = texture.alpha / 100000 + } + let imgInsets = null + if (texture.insets) { + let top = texture.insets[0] / 100000 + let left = texture.insets[1] / 100000 + let bottom = texture.insets[2] / 100000 + let right = texture.insets[3] / 100000 + let x = img.width * left + let y = img.height * top + let w = img.width * (1 - left - right) + let h = img.height * (1 - top - bottom) + imgInsets = [x, y, w, h] + } + if (texture.stretch) { + let top = texture.stretch[0] / 100000 + let left = texture.stretch[1] / 100000 + let bottom = texture.stretch[2] / 100000 + let right = texture.stretch[3] / 100000 + let x = width * left + let y = height * top + let w = width * (1 - left - right) + let h = height * (1 - top - bottom) + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) + } else { + patternCtx.drawImage(img, x, y, w, h) + } + } else if (texture.alignment) { + let x = 0, y = 0 + if (texture.alignment == 'CENTER') { + if (width > anchor[2]) { + x = (width - anchor[2]) / 2 + } + if (height > anchor[3]) { + y = (height - anchor[3]) / 2 + } + } + patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) + } else { + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) + } else { + patternCtx.drawImage(img, 0, 0, width, height) + } + } + if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { + try { + // 重新着色 + let color = texture.duoTone[0].realColor + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) + let data = imageData.data + for(var i = 0; i < data.length; i += 4) { + let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 + // black / white + let prst = texture.duoTonePrst == 'white' ? 255 : 0 + data[i] = gray * r + (1 - gray) * prst + data[i + 1] = gray * g + (1 - gray) * prst + data[i + 2] = gray * b + (1 - gray) * prst + } + patternCtx.putImageData(imageData, 0, 0) + } catch(e) { /* empty */ } + } + return ctx.createPattern(patternCanvas, mode) + } + + function toColor(colorObj, defaultColor) { + if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { + return defaultColor || 'transparent' + } + let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let a = ((color >> 24) & 255) / 255 + if (colorObj.realColor == null) { + if (colorObj.alpha != null && colorObj.alpha != -1) { + if (colorObj.alpha > 1000) { + a = colorObj.alpha / 100000 + } else { + a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 + } + a = Math.min(1, Math.max(0, a)) + } + if (colorObj.lumMod && colorObj.lumMod > 0) { + let value = colorObj.lumMod / 100000 + r = r * value + g = g * value + b = b * value + } + if (colorObj.lumOff && colorObj.lumOff > 0) { + let value = colorObj.lumOff / 100000 + r += 255 * value + g += 255 * value + b += 255 * value + } + } + return `rgba(${r}, ${g}, ${b}, ${a})` + } + + function toColorValue(r, g, b, a) { + a = (a == null ? 255 : a) + return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 + } + + function loadImage(src, anonymous) { + return new Promise(resolve => { + if (!src) { + resolve() + return + } + let cacheKey + if (src.length < 15) { + cacheKey = src + } else { + cacheKey = src.length + '_' + src.substring(src.length - 15) + } + let img = imageCache[cacheKey] + if (img == null) { + img = new Image() + if (imageCrossOrigin || anonymous) { + let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) + if (!eqOrigin) { + // anonymous / use-credentials + img.crossOrigin = imageCrossOrigin || 'anonymous' + } + } + img.src = src + img.onload = function() { + imageCache[cacheKey] = img + resolve(img) + } + img.onerror = function (e) { + resolve() + console.log('图片加载失败: ', src, e) + } + } else { + resolve(img) + } + }) + } + + function value2px(v, isEmu) { + if (isEmu) { + return +v / 12700 + } else { + return +v + } + } + + function value2emu(v) { + return +v * 12700 + } + + function getTfx(x, div) { + if (div) { + return x / (ctx.getTransform().a / ctx.scaleX) + } else { + return x * (ctx.getTransform().a / ctx.scaleX) + } + } + + function getTfy(y, div) { + if (div) { + return y / (ctx.getTransform().d / ctx.scaleY) + } else { + return y * (ctx.getTransform().d / ctx.scaleY) + } + } + + function splitWords(str) { + if (!str) { + return [] + } + let pattern = /^[0-9a-zA-Z]+$/ + let array = [] + let item = '' + let math = null + for (let i = 0; i < str.length; i++) { + if (str[i] == '\n') { + if (item) { + array.push({ text: item, word: math }) + } + array.push({ text: '\n', word: false }) + item = '' + math = null + } else { + let _math = pattern.test(str[i]) + if (math == null) { + math = _math + item += str[i] + } else if (_math == math) { + item += str[i] + } else { + array.push({ text: item, word: math }) + item = str[i] + math = _math + } + } + } + if (item) { + array.push({ text: item, word: math }) + } + return array + } + + function isSymbol(s) { + switch (s) { + case ',': + case '.': + case '!': + case '?': + case ')': + case ';': + case ',': + case '。': + case '!': + case '?': + case ')': + case ';': + case '”': + case ' ': + return true + } + return false + } + + function rgb2hsv(r, g, b) { + r /= 255, g /= 255, b /= 255 + let max = Math.max(r, g, b), min = Math.min(r, g, b) + let h, s, v = max + let d = max - min + s = max == 0 ? 0 : d / max + if (max == min) { + h = 0 + } else { + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break + case g: h = (b - r) / d + 2; break + case b: h = (r - g) / d + 4; break + } + h /= 6 + } + return [h, s, v] + } + + function hsv2rgb(h, s, v) { + let r, g, b + let i = Math.floor(h * 6) + let f = h * 6 - i + let p = v * (1 - s) + let q = v * (1 - f * s) + let t = v * (1 - (1 - f) * s) + switch (i % 6) { + case 0: r = v, g = t, b = p; break + case 1: r = q, g = v, b = p; break + case 2: r = p, g = v, b = t; break + case 3: r = p, g = q, b = v; break + case 4: r = t, g = p, b = v; break + case 5: r = v, g = p, b = q; break + } + return [r * 255, g * 255, b * 255] + } + + function text(obj) { + if (obj == null) { + return null + } + let text = obj.text + if (text != null) { + return text + } + if (obj.children != null && obj.children.length > 0) { + let textAll = '' + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + if (p.children == null) { + continue + } + let pText = '' + for (let j = 0; j < p.children.length; j++) { + let r = p.children[j] + if (r.text == null) { + continue + } + pText += r.text + } + if (pText) { + textAll += (pText + '\n') + } + } + if (textAll.length > 0) { + textAll = textAll.substring(0, textAll.length - 1) + } + return textAll + } + return '' + } + + this.setTemplateHandle = (_templateHandle) => { + templateHandle = _templateHandle + } + + this.idMap = idMap + this.recursion = recursion + this.drawGeometry = drawGeometry + this.drawElement = drawElement + this.toPaint = toPaint + this.toColor = toColor + this.toColorValue = toColorValue + this.loadImage = loadImage + this.text = text + +} + +export { Ppt2Canvas } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js new file mode 100644 index 0000000..3ff7443 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js @@ -0,0 +1,2265 @@ +/* eslint-disable no-unused-vars */ +import { geometryPaths } from './geometry.js' +import { drawChart } from './chart.js' + +function D3Element(element) { + this.attr = function (k, v) { + if (v == undefined) { + return element.getAttribute(k) + } else { + element.setAttribute(k, v) + return this + } + } + this.style = function (k, v) { + if (v == undefined) { + return element.style[k] + } else { + element.style[k] = v + return this + } + } + this.text = function (v) { + if (v == undefined) { + return element.textContent + } else { + element.textContent = v + return this + } + } + this.append = function (tag) { + let node = document.createElementNS('http://www.w3.org/2000/svg', tag) + element.appendChild(node) + return new D3Element(node) + } + this.parent = function () { + return element.parentNode ? new D3Element(element.parentNode) : null + } + this.node = function () { + return element + } + this.html = function (v) { + if (v == undefined) { + return element.innerHTML + } else { + element.innerHTML = v + return this + } + } + this.translate = function (x, y, start) { + let transform = element.getAttribute('transform') + if (x == undefined && y == undefined) { + x = y = 0 + if (transform) { + let idx = transform.indexOf('translate') + if (idx > -1) { + let arr = transform.substring(idx + 10, transform.indexOf(')', idx + 10)).replace('(', '').split(',') + x = parseFloat(arr[0] || 0) + y = parseFloat(arr[1] || 0) + } + } + return { x, y } + } else { + if (y == undefined) { + y = 0 + } + if (transform) { + let idx = transform.indexOf('translate') + if (idx > -1) { + let eIdx = transform.indexOf(')', idx + 10) + transform = transform.substring(0, idx) + `translate(${x}, ${y})` + transform.substring(eIdx + 1) + element.setAttribute('transform', transform.trim()) + } else { + element.setAttribute('transform', start ? `translate(${x}, ${y}) ${transform}`: `${transform} translate(${x}, ${y})`) + } + } else { + element.setAttribute('transform', `translate(${x}, ${y})`) + } + return this + } + } + this.scale = function (x, y, start) { + let transform = element.getAttribute('transform') + if (x == undefined && y == undefined) { + x = y = 1 + if (transform) { + let idx = transform.indexOf('scale') + if (idx > -1) { + let arr = transform.substring(idx + 6, transform.indexOf(')', idx + 6)).replace('(', '').split(',') + x = parseFloat(arr[0] || 0) + y = arr[1] == undefined ? x : parseFloat(arr[1]) + } + } + return { x, y } + } else { + if (y == undefined) { + y = x + } + if (transform) { + let idx = transform.indexOf('scale') + if (idx > -1) { + let eIdx = transform.indexOf(')', idx + 6) + transform = transform.substring(0, idx) + `scale(${x}, ${y})` + transform.substring(eIdx + 1) + element.setAttribute('transform', transform.trim()) + } else { + element.setAttribute('transform', start ? `scale(${x}, ${y}) ${transform}` : `${transform} scale(${x}, ${y})`) + } + } else { + element.setAttribute('transform', `scale(${x}, ${y})`) + } + return this + } + } + this.rotate = function (rotate, x, y, start) { + let transform = element.getAttribute('transform') + if (rotate == undefined) { + x = y = 0 + if (transform) { + let idx = transform.indexOf('rotate') + if (idx > -1) { + let arr = transform.substring(idx + 7, transform.indexOf(')', idx + 7)).replace('(', '').split(',') + rotate = parseFloat(arr[0] || 0) + x = arr[1] == undefined ? 0 : parseFloat(arr[1]) + y = arr[2] == undefined ? 0 : parseFloat(arr[2]) + } + } + return { rotate, x, y } + } else { + let transformRotate = rotate ? `rotate(${rotate})` : '' + if (x != undefined && y != undefined) { + transformRotate = `rotate(${rotate}, ${x}, ${y})` + } + if (transform) { + let idx = transform.indexOf('rotate') + if (idx > -1) { + let eIdx = transform.indexOf(')', idx + 7) + transform = transform.substring(0, idx) + transformRotate + transform.substring(eIdx + 1) + element.setAttribute('transform', transform.trim()) + } else { + element.setAttribute('transform', start ? `${transformRotate} ${transform}` : `${transform} ${transformRotate}`) + } + } else { + element.setAttribute('transform', transformRotate) + } + return this + } + } +} + +const d3 = { + select: function (o) { + return new D3Element((typeof o == 'string') ? document.querySelector(o) : o) + }, + addEventListener: function (type, event, fun) { + if (type === 'window') { + window.addEventListener(event, fun) + } else if (type === 'document') { + document.addEventListener(event, fun) + } + } +} + +function Ppt2Svg(_svg, svgWidth, svgHeight) { + var pptx = null + var page = null + var imageCache = {} + var pageIndex = 0 + var ctx = {} + var idMap = {} + var counter = 0 + var zoom = 1 + var defs = null + var mode = 'view' + var pointList = [] + var mTimer = null + var currentPoint = null + var currentSelect = null + // eslint-disable-next-line @typescript-eslint/no-this-alias + const $this = this + const svg = d3.select((typeof _svg == 'string') ? ('#' + _svg) : _svg) + .attr('width', svgWidth || 960) + .attr('height', svgHeight || 540) + + this.drawPptx = (pptxObj, pageIdx, selectElementId) => { + removePoint() + removeElementMoveScale() + ctx = {} + idMap = {} + imageCache = {} + counter = 0 + pptx = pptxObj + pageIndex = pageIdx + zoom = svgWidth / pptx.width + svg.html('') + defs = svg.append('defs') + page = pptxObj.pages[pageIdx] + let placeholder = {} + let slideMasterIdx = page.extInfo.slideMasterIdx + if (slideMasterIdx != null && pptxObj.slideMasters) { + let slideMaster = pptxObj.slideMasters[slideMasterIdx] + let slideLayoutIdx = page.extInfo.slideLayoutIdx + let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null + drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) + drawSlideMaster(slideMaster, slideLayout, placeholder) + if (slideLayout) { + drawSlideLayout(slideLayout, placeholder) + } + } else { + drawBackground(page.extInfo.background) + } + if (!page.children) { + return + } + recursion(page.children, obj => { + idMap[obj.id] = obj + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + // 继承母版占位符 + let element_property = obj.extInfo.property + let placeholder_property = placeholder[element_property.placeholder.type] || {} + for (let k in placeholder_property) { + if (element_property[k] == null) { + element_property[k] = placeholder_property[k] + } + } + } + }) + for (let i = 0; i < page.children.length; i++) { + drawElement(page.children[i]) + } + recursion(page.children, obj => { + idMap[obj.id] = obj + }) + calcPointList(page) + if (selectElementId) { + addElementMoveScale(idMap[selectElementId]) + } + } + + this.svgNode = () => { + return svg.node() + } + + this.resetSize = (_svgWidth, _svgHeight) => { + svgWidth = _svgWidth || svgWidth + svgHeight = _svgHeight || svgHeight + svg.attr('width', svgWidth).attr('height', svgHeight) + if (pptx) { + zoom = svgWidth / pptx.width + this.drawPptx(pptx, pageIndex) + } + } + + this.setMode = (_mode) => { + // view / edit + mode = _mode || 'view' + return mode + } + + function scaleAnchor(point) { + return point ? [...point.map(s => s * zoom)] : point + } + + function scaleValue(value) { + return value ? value * zoom : value + } + + function shapeHandle(property, parent) { + let g = parent.append('g') + let anchor = scaleAnchor(property.anchor) + if (!anchor) { + g.attr('groupFlipX', ctx.groupFlipX || 1) + g.attr('groupFlipY', ctx.groupFlipY || 1) + return g + } + let transform = [] + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + transform.push(`rotate(${property.rotation || 0}, ${cx}, ${cy})`) + if (property.rotation) { + if (property.realType == 'Group') { + ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation + } + } + if (property.flipVertical) { + transform.push(`translate(${cx}, ${cy})`) + transform.push(`scale(1, -1)`) + transform.push(`translate(${-cx}, ${-cy})`) + if (property.realType == 'Group') { + ctx.groupFlipY = -(ctx.groupFlipY || 1) + } + } + if (property.flipHorizontal) { + transform.push(`translate(${cx}, ${cy})`) + transform.push(`scale(-1, 1)`) + transform.push(`translate(${-cx}, ${-cy})`) + if (property.realType == 'Group') { + ctx.groupFlipX = -(ctx.groupFlipX || 1) + } + } + // 嵌套容器 Group + let interior = scaleAnchor(property.interiorAnchor) + if (interior && interior.length > 0) { + let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] + let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] + let tx = anchor[0] - interior[0] * scaleX + let ty = anchor[1] - interior[1] * scaleY + transform.push(`translate(${tx}, ${ty})`) + ctx._interior = ctx.interior + ctx.interior = { scaleX, scaleY, tx, ty } + } else if (property.realType == 'Group') { + ctx._interior = ctx.interior + ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } + } else if (ctx.interior) { + g.attr('interior', JSON.stringify(ctx.interior)) + } + if (transform.length > 0) { + g.attr('transform', transform.join(' ')) + } + g.attr('groupFlipX', ctx.groupFlipX || 1) + g.attr('groupFlipY', ctx.groupFlipY || 1) + return g + } + + function drawBackground(background) { + if (!background) { + ctx.bgAnchor = null + ctx.bgFillStyle = null + return + } + let anchor = scaleAnchor(background.anchor) + ctx.bgAnchor = anchor + ctx.bgFillStyle = background.fillStyle + let fill = toPaint(background.fillStyle, anchor) + svg.append('rect') + .attr('x', 0).attr('y', 0) + .attr('width', anchor[2]) + .attr('height', anchor[3]) + .attr('fill', fill) + .node().addEventListener('click', function (e) { + if (!currentPoint) { + removeElementMoveScale() + } + }) + } + + function drawSlideMaster(slideMaster, slideLayout, placeholder) { + recursion(slideMaster.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + if (slideLayout && slideLayout.noMaster) { + return + } + for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { + drawElement(slideMaster.children[i]) + } + } + + function drawSlideLayout(slideLayout, placeholder) { + recursion(slideLayout.children, obj => { + if (obj.extInfo.property && obj.extInfo.property.placeholder) { + obj.noDraw = true + placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property + } + }) + for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { + drawElement(slideLayout.children[i]) + } + } + + function recursion(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.children && c.children.length > 0) { + recursion(c.children, fn) + } + } + } + + function drawElement(obj, parent) { + if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { + // console.log('ignore element:', obj) + return + } + if (!parent) { + parent = svg + } + if (obj.type == 'text' || obj.type == 'freeform') { + drawText(obj, parent) + } else if (obj.type == 'image') { + drawImage(obj, parent) + } else if (obj.type == 'diagram') { + drawDiagram(obj, parent) + } else if (obj.type == 'container') { + drawContainer(obj, parent) + } else if (obj.type == 'table') { + drawTable(obj, parent) + } else if (obj.type == 'connector') { + drawConnector(obj, parent) + } else if (obj.type == 'graphicFrame') { + drawGraphicFrame(obj, parent) + } + } + + this.redrawElementWithId = (id) => { + let obj = idMap[id] + if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { + return + } + let parent = idMap[obj.pid] + while (parent) { + if (parent.type == 'container') { + // 重新渲染页面 + this.drawPptx(pptx, pageIndex, id) + return + } + parent = idMap[parent.pid] + } + let list = [] + if (obj.point) { + let x = obj.point[0] + let y = obj.point[1] + let endX = obj.point[0] + obj.point[2] + let endY = obj.point[1] + obj.point[3] + for (let i = 0; i < pointList.length; i++) { + let point = pointList[i] + if (point.obj.id == id) { + break + } + if (point.x >= x && point.y >= y && point.endX <= endX && point.endY <= endY) { + list.push(point.obj) + } else if (point.y > y && point.y < endY && (point.x > x && point.x < endX || point.endX > x && point.endX < endX)) { + list.push(point.obj) + } else if (point.x > x && point.x < endX && (point.y > y && point.y < endY || point.endY > y && point.endY < endY)) { + list.push(point.obj) + } + if (list.length > 0) { + // 重新渲染页面 + this.drawPptx(pptx, pageIndex, id) + return + } + } + } + let element = document.getElementById('g-' + obj.id) + if (element) { + element.remove() + let parent = element.parentNode ? d3.select(element.parentNode) : null + drawElement(obj, parent) + } + page && calcPointList(page) + if (currentSelect) { + addElementMoveScale(currentSelect) + } + } + + function drawText(obj, parent) { + let property = obj.extInfo.property + let geometryName = (property.geometry || {}).name || 'rect' + let g = shapeHandle(property, parent) + g.attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + if (geometryName == 'tableColumn') { + drawTableColumn(property, g) + } else { + drawGeometry(property, g) + } + if (!obj.children || obj.children.length == 0) { + return + } + drawTextWithG(g, obj) + } + + function drawTextWithG(g, obj) { + let childNodes = g.node().childNodes + for (let i = childNodes.length - 1; i >= 0; i--) { + if (childNodes[i].tagName == 'text') { + childNodes[i].remove() + } + } + if (!obj.children || obj.children.length == 0) { + return + } + let property = obj.extInfo.property + let anchor = scaleAnchor(property.anchor) + let wordWrap = property.textWordWrap ?? true + let textInsets = property.textInsets || [0, 0, 0, 0] + let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 + let verticalAlignment = property.textVerticalAlignment + let textNode = g.append('text').attr('id', obj.id).attr('x', anchor[0]).attr('y', anchor[1]) + textNode.style('user-select', 'none') + if (isVertical) { + textNode.style('writing-mode', 'vertical-rl') + } + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + let x = parseInt(g.attr('groupFlipX') || ctx.groupFlipX || 1) + let y = parseInt(g.attr('groupFlipY') || ctx.groupFlipX || 1) + let transform = [] + if (property.flipHorizontal) { + x *= -1 + } + if (property.flipVertical) { + y *= -1 + } + if (y == -1) { + if (x == 1) { + transform.push(`translate(${cx}, ${cy})`) + transform.push(`scale(-1, 1)`) + transform.push(`translate(${-cx}, ${-cy})`) + } + } else if (x == -1) { + transform.push(`translate(${cx}, ${cy})`) + transform.push(`scale(-1, 1)`) + transform.push(`translate(${-cx}, ${-cy})`) + } + if (transform.length > 0) { + textNode.attr('transform', transform.join(' ')) + } + let marginTop = property.strokeStyle ? scaleValue(property.strokeStyle.lineWidth || 1) : 0 + let maxFontSize = 0 + let maxWidth = anchor[2] - textInsets[1] - textInsets[3] + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + let p_property = p.extInfo.property + let textAlign = p_property.textAlign + let lineSpacing = p_property.lineSpacing > 0 ? (p_property.lineSpacing / 100) : (1 + Math.abs(p_property.lineSpacing || 0) / 100) + let createPNode = () => { + let pNode = textNode.append('tspan').attr('id', p.id) + if (textAlign == 'CENTER') { + pNode.attr('x', anchor[0] + (anchor[2] - textInsets[1] - textInsets[3]) / 2 + textInsets[1]) + pNode.attr('text-anchor', 'middle') + } else if (textAlign == 'RIGHT') { + pNode.attr('x', anchor[0] + anchor[2] - textInsets[3]) + pNode.attr('text-anchor', 'end') + } else { + pNode.attr('x', anchor[0] + textInsets[1]) + pNode.attr('text-anchor', 'start') + } + return pNode + } + let pNode = createPNode() + for (let i = 0; i < p.children.length; i++) { + let r = p.children[i] + let r_property = r.extInfo.property + if (r_property.slideNum) { + r.text = (pageIndex + 1) + '' + } + let fontSize = scaleValue(r_property.fontSize || 16) + let createRNode = (_pNode) => { + let rNode = _pNode.append('tspan').attr('id', r.id) + if (r_property.bold) { + rNode.style('font-weight', 'bold') + } + if (r_property.italic) { + rNode.style('font-style', 'italic') + } + if (r_property.underlined) { + rNode.style('text-decoration', 'underline') + } + rNode.style('cursor', 'text') + rNode.style('font-size', fontSize + 'px') + rNode.style('font-family', (r_property.fontFamily || '等线')) + let filter = toShadow(r_property.shadow, anchor) + if (filter) { + rNode.attr('filter', filter) + } + if (r_property.line && (r_property.fontColor == null || r_property.fontColor.type == 'noFill')) { + let fillStyle = toPaint(r_property.line.paint, anchor) + rNode.attr('fill', 'none') + rNode.attr('stroke', fillStyle) + rNode.attr('stroke-width', scaleValue(r_property.line.lineWidth || 1)) + } else { + let params = {} + if (r_property.fontColor.type == 'texture') { + params.tx = anchor[0] + params.ty = anchor[1] + marginTop + } + let fillStyle = toPaint(r_property.fontColor, anchor, params) + rNode.attr('fill', fillStyle) + } + addRunTextEvent(rNode, obj) + return rNode + } + maxFontSize = Math.max(fontSize, maxFontSize) + let rNode = createRNode(pNode) + if (isVertical) { + // 竖版 + rNode.text(r.text) + } else { + // 横版 + rNode.text(r.text) + if (wordWrap && pNode.node().getComputedTextLength() > maxWidth && r.text.length > 1) { + // 自动换行 + let start = 0 + for (let s = 1; s <= r.text.length; s++) { + let text = r.text.substring(start, s) + rNode.text(text) + if (pNode.node().getComputedTextLength() > maxWidth - maxFontSize / 2) { + marginTop += (maxFontSize * lineSpacing) + pNode.attr('y', anchor[1] + marginTop) + pNode = createPNode() + rNode = createRNode(pNode) + start = s + } + } + } + } + } + if (isVertical) { + if (verticalAlignment == 'MIDDLE') { + pNode.attr('x', anchor[0] + maxFontSize * (obj.children.length - i - 1) + (anchor[2] - maxFontSize * obj.children.length) / 2) + } else if (verticalAlignment == 'TOP') { + pNode.attr('x', anchor[0] + anchor[2] - maxFontSize * (i + 1)) + } else { + pNode.attr('x', anchor[0] + maxFontSize * (obj.children.length - i - 1)) + } + pNode.attr('y', anchor[1]) + } else { + marginTop += (maxFontSize * lineSpacing) + pNode.attr('y', anchor[1] + marginTop) + } + } + let yHeight = 0 + if (verticalAlignment == 'MIDDLE') { + let height = textNode.node().getBBox().height + yHeight = (anchor[3] - height - textInsets[0] - textInsets[2]) / 2 + textInsets[0] - maxFontSize / 4 + } else if (verticalAlignment == 'BOTTOM') { + let height = textNode.node().getBBox().height + yHeight = anchor[3] - height - textInsets[2] + } + if (yHeight != 0) { + let childNodes = textNode.node().childNodes + for (let i = 0; i < childNodes.length; i++) { + let pNode = childNodes[i] + let y = +pNode.getAttribute('y') + yHeight + pNode.setAttribute('y', y) + } + } + } + + function drawImage(obj, parent) { + let property = obj.extInfo.property + let g = shapeHandle(property, parent) + g.attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + if (property.fillStyle && property.fillStyle.texture) { + property.fillStyle.texture.imageData = property.image + // 图片自带拉伸 + property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] + } else { + property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } + } + drawGeometry(property, g, obj.id) + } + + function drawTableColumn(property, parent) { + let anchor = scaleAnchor(property.anchor) + let x = anchor[0] - 1 + let endX = anchor[0] + anchor[2] + 1 + let y = anchor[1] - 1 + let endY = anchor[1] + anchor[3] + 1 + let borders = scaleAnchor(property.borders) // top/left/bottom/right + // top + let top = borders[0] + let lineWidth = scaleValue(top.lineWidth) + let stroke = toColor({ color: top.color }, 'white') + parent.append('line') + .attr('x1', x).attr('y1', y) + .attr('x2', endX).attr('y2', y) + .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) + // right + let right = borders[3] + lineWidth = scaleValue(right.lineWidth) + stroke = toColor({ color: right.color }, 'white') + parent.append('line') + .attr('x1',endX).attr('y1', y) + .attr('x2', endX).attr('y2', endY) + .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) + // bottom + let bottom = borders[2] + lineWidth = scaleValue(bottom.lineWidth) + stroke = toColor({ color: bottom.color }, 'white') + parent.append('line') + .attr('x1',endX).attr('y1', endY) + .attr('x2', x).attr('y2', endY) + .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) + // left + let left = borders[1] + lineWidth = scaleValue(left.lineWidth) + stroke = toColor({ color: left.color }, 'white') + parent.append('line') + .attr('x1',x).attr('y1', endY) + .attr('x2', x).attr('y2', y) + .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) + if (property.fillStyle) { + let fill = toPaint(property.fillStyle, anchor) + parent.append('rect') + .attr('x', anchor[0]).attr('y', anchor[1]) + .attr('width', anchor[2]) + .attr('height', anchor[3]) + .attr('fill', fill) + .attr('stroke', 'none') + } + } + + function drawDiagram(obj, parent) { + let property = obj.extInfo.property + let anchor = scaleAnchor(property.anchor) + let g = parent.append('g').attr('id', obj.id).attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + g.attr('transform', `translate(${anchor[0]}, ${anchor[1]})`) + for (let i = 0; i < obj.children.length; i++) { + drawElement(obj.children[i], g) + } + } + + function drawContainer(obj, parent) { + let property = obj.extInfo.property + let _groupFlipX = ctx.groupFlipX + let _groupFlipY = ctx.groupFlipY + let _groupRotation = ctx.groupRotation + let g = shapeHandle(property, parent) + g.attr('id', obj.id).attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + if (property.realType == 'Group') { + let parentGroupFillStyle = ctx.groupFillStyle + let groupFillStyle = property.groupFillStyle + if (groupFillStyle) { + groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) + groupFillStyle.groupAnchor = scaleAnchor(property.anchor) + if (parentGroupFillStyle) { + groupFillStyle.parentGroupFillStyle = parentGroupFillStyle + } + } + ctx.groupFillStyle = groupFillStyle + let copyChildren = JSON.parse(JSON.stringify(obj.children)) + recursionGroupChildren(copyChildren, c => { + if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { + let anchor = c.extInfo.property.anchor + anchor[0] *= ctx.interior.scaleX + anchor[1] *= ctx.interior.scaleY + anchor[2] *= ctx.interior.scaleX + anchor[3] *= ctx.interior.scaleY + } + }) + for (let i = 0; i < copyChildren.length; i++) { + drawElement(copyChildren[i], g) + } + ctx.interior = ctx._interior + } else { + for (let i = 0; i < obj.children.length; i++) { + drawElement(obj.children[i], g) + } + } + ctx.groupFlipX = _groupFlipX + ctx.groupFlipY = _groupFlipY + ctx.groupRotation = _groupRotation + } + + function recursionGroupChildren(children, fn) { + if (!children) { + return + } + for (let i = 0; i < children.length; i++) { + let c = children[i] + fn(c) + if (c.extInfo && c.extInfo.property.realType == 'Group') { + continue + } + if (c.children && c.children.length > 0) { + recursionGroupChildren(c.children, fn) + } + } + } + + function drawConnector(obj, parent) { + let property = obj.extInfo.property + let g = parent.append('g').attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + drawGeometry(property, g, obj.id) + } + + function drawGraphicFrame(obj, parent) { + let property = obj.extInfo.property + let anchor = scaleAnchor(property.anchor) + let g = parent.append('g').attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { + drawChart(property.chart, [0, 0, anchor[2], anchor[3]]).then(canvas => { + let imgSrc = canvas.toDataURL('image/png') + let fill = toPaint({ 'type': 'texture', texture: { 'imageData': imgSrc, stretch: [0, 0, 0, 0] } }, anchor) + g.append('rect') + .attr('id', obj.id) + .attr('width', anchor[2]) + .attr('height', anchor[3]) + .attr('transform', `translate(${anchor[0]}, ${anchor[1]})`) + .attr('fill', fill) + }) + } + } + + function drawTable(obj, parent) { + let property = obj.extInfo.property + let g = parent.append('g').attr('id', obj.id).attr('id', 'g-' + obj.id) + addElementEvent(g, obj) + for (let i = 0; i < obj.children.length; i++) { + let row = obj.children[i] + drawTableRow(obj, row, g) + } + } + + function drawTableRow(table, row, parent) { + let property = row.extInfo.property + for (let i = 0; i < row.children.length; i++) { + let column = row.children[i] + drawText(column, parent) + } + } + + function drawGeometry(property, parent, id) { + if (!parent) { + parent = svg + } + let anchor = scaleAnchor(property.anchor) + let stroke = null + let lineWidth = scaleValue(1) + if (property.strokeStyle) { + lineWidth = scaleValue(property.strokeStyle.lineWidth || 1) + stroke = toPaint(property.strokeStyle.paint, anchor) + } + let paths = geometryPaths(property, zoom) + for (let i = 0; i < paths.length; i++) { + let path = paths[i] + let pathNode = parent.append('path') + if (id) { + pathNode.attr('id', id) + } + pathNode.attr('d', path.path) + let transform = `translate(${anchor[0]},${anchor[1]})` + if (path.scaleX && path.scaleY) { + transform += ` scale(${path.scaleX || 1},${path.scaleY || 1})` + } + pathNode.attr('transform', transform) + let fill = null + if (property.fillStyle) { + let scaleX = 1 / path.scaleX + let scaleY = 1 / path.scaleY + let params = { scaleX, scaleY } + if (property.fillStyle.type == 'bgFill') { + if (ctx.interior) { + params.tx = -ctx.interior.tx - anchor[0] + params.ty = -ctx.interior.ty - anchor[1] + } else { + params.tx = -anchor[0] + params.ty = -anchor[1] + } + params.width = anchor[2] + params.height = anchor[3] + params.rotation = -((property.rotation || 0) + (ctx.groupRotation || 0)) + } + fill = toPaint(property.fillStyle, anchor, params) + } + if (path.filled && fill) { + pathNode.attr('fill', fill) + } else { + pathNode.attr('fill', 'transparent') + } + if (path.stroked) { + pathNode.attr('stroke', stroke) + pathNode.attr('stroke-width', path.scaleY ? lineWidth / path.scaleY : lineWidth) + } + let filter = toShadow(property.shadow, anchor, path.scaleX, path.scaleY) + if (filter) { + pathNode.attr('filter', filter) + } + } + } + + function toShadow(shadow, anchor, scaleX, scaleY) { + if (!shadow) { + return null + } + scaleX = scaleX || 1 + scaleY = scaleY || 1 + let stdDeviation = (shadow.blur || 0) / Math.max(scaleX, scaleY) / 5 + let distance = scaleValue(shadow.distance) + let color = toColor(shadow.fillStyle.color) + let filterId = 'shadow' + (++counter) + let filter = defs.append('filter').attr('id', filterId) + if (anchor && distance && (distance >= anchor[2] / 2 || distance >= anchor[3] / 2)) { + filter.attr('x', '-100%').attr('y', '-100%').attr('width', '400%').attr('height', '400%') + } else { + filter.attr('x', '-50%').attr('y', '-50%').attr('width', '200%').attr('height', '200%') + } + filter.append('feGaussianBlur').attr('in', 'SourceAlpha').attr('stdDeviation', stdDeviation).attr('result', 'blur') + filter.append('feFlood').attr('flood-color', color).attr('result', 'color') + filter.append('feComposite').attr('in', 'color').attr('in2', 'blur').attr('operator', 'in').attr('result', 'shadow') + if (distance) { + let radians = (shadow.angle || 0) * Math.PI / 180 + let x = 0, y = 0 + let rx = distance / scaleX + let ry = distance / scaleY + let shadowOffsetX = x + rx * Math.cos(radians) + let shadowOffsetY = y + ry * Math.sin(radians) + filter.append('feOffset').attr('dx', shadowOffsetX).attr('dy', shadowOffsetY).attr('result', 'offsetBlur') + } + let feMerge = filter.append('feMerge') + feMerge.append('feMergeNode').attr('in', 'offsetBlur') + feMerge.append('feMergeNode').attr('in', 'SourceGraphic') + return `url(#${filterId})` + } + + function toPaint(paint, anchor, params) { + if (!paint) { + return 'transparent' + } else if (paint.type == 'noFill') { + // 无填充 + return 'transparent' + } else if (paint.type == 'color') { + // 颜色 + return toColor(paint.color) + } else if (paint.type == 'bgFill') { + // 背景填充 + if (ctx.bgFillStyle) { + return toPaint(ctx.bgFillStyle, ctx.bgAnchor || anchor, params) + } else { + return 'transparent' + } + } else if (paint.type == 'groupFill') { + // 组合背景 + let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle + if (groupFillStyle) { + return toPaint(groupFillStyle, scaleAnchor(groupFillStyle.groupAnchor) || anchor, params) + } else { + return 'transparent' + } + } else if (paint.type == 'gradient') { + // 渐变 + let gradient = paint.gradient + let x = 0, y = 0 + let width = anchor[2], height = anchor[3] + let centerX = x + width / 2 + let centerY = y + height / 2 + let gradientNode + // linear,circular,rectangular,shape + if (gradient.gradientType == 'circular') { + // 射线 + let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 + let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 + // let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) + let _cx = ((cx / width) * 100).toFixed(0) + '%' + let _cy = ((cy / height) * 100).toFixed(0) + '%' + let _r = (gradient.insets[1] * 100).toFixed(0) + '%' + gradientNode = defs.append('radialGradient').attr('cx', _cx).attr('cy', _cy).attr('r', _r).attr('fx', _cx).attr('fy', _cy) + } else { + // 线性 + let startX = x + let startY = centerY + let endX = x + width + let endY = centerY + if (gradient.angle) { + let radians = gradient.angle * Math.PI / 180 + let midX = (startX + endX) / 2 + let midY = (startY + endY) / 2 + let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) + let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) + let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) + let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) + startX = newStartX + startY = newStartY + endX = newEndX + endY = newEndY + } + let x1 = ((startX / width) * 100).toFixed(0) + '%' + let y1 = ((startY / height) * 100).toFixed(0) + '%' + let x2 = ((endX / width) * 100).toFixed(0) + '%' + let y2 = ((endY / height) * 100).toFixed(0) + '%' + gradientNode = defs.append('linearGradient').attr('x1', x1).attr('y1', y1).attr('x2', x2).attr('y2', y2) + } + let gradientId = 'gradient' + (++counter) + gradientNode.attr('id', gradientId) + for (let i = 0; i < gradient.colors.length; i++) { + let color = toColor(gradient.colors[i]) + let offset = (gradient.fractions[i] * 100).toFixed(0) + '%' + gradientNode.append('stop').attr('offset', offset).attr('stop-color', color) + } + return `url(#${gradientId})` + } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { + return 'transparent' + } else if (paint.type == 'texture') { + // 图片或纹理 + let texture = paint.texture + let patternId = 'pattern' + (++counter) + let patternNode = defs.append('pattern').attr('id', patternId).attr('patternUnits', 'userSpaceOnUse') + if (params) { + let transform = [] + if (params.scaleX && params.scaleY) { + transform.push(`scale(${params.scaleX}, ${params.scaleY})`) + } + if (params.rotation) { + let width = params.width || anchor[2] + let height = params.height || anchor[3] + transform.push(`rotate(${params.rotation}, ${width / 2}, ${height / 2})`) + } + if (params.tx != null && params.ty != null) { + transform.push(`translate(${params.tx}, ${params.ty})`) + } + if (transform.length > 0) { + patternNode.attr('patternTransform', transform.join(' ')) + } + } + loadImage(texture.imageData).then(img => { + if (img) { + texturePattern(patternNode, img, texture, anchor) + } + }) + return `url(#${patternId})` + } else if (paint.type == 'pattern') { + // 图案 + let pattern = paint.pattern + // let prst = pattern.prst + let fgColor = pattern.fgColor.realColor + let bgColor = pattern.bgColor.realColor + let width = anchor[2], height = anchor[3] + let imgCanvas = document.createElement('canvas') + imgCanvas.width = width + imgCanvas.height = height + let imgCtx = imgCanvas.getContext('2d') + imgCtx.imageSmoothingEnabled = true + imgCtx.imageSmoothingQuality = 'high' + let imgData = imgCtx.createImageData(width, height) + let line = 0 + for (let i = 0; i < imgData.data.length; i += 4) { + if (++line % 16 == 0) { + // 前景 + imgData.data[i + 0] = (fgColor >> 16) & 255 + imgData.data[i + 1] = (fgColor >> 8) & 255 + imgData.data[i + 2] = (fgColor >> 0) & 255 + imgData.data[i + 3] = (fgColor >> 24) & 255 + } else { + // 背景 + imgData.data[i + 0] = (bgColor >> 16) & 255 + imgData.data[i + 1] = (bgColor >> 8) & 255 + imgData.data[i + 2] = (bgColor >> 0) & 255 + imgData.data[i + 3] = (bgColor >> 24) & 255 + } + if (i % 400 == 0) { + line += 2 + } + } + imgCtx.putImageData(imgData, 0, 0) + let imgSrc = imgCanvas.toDataURL('image/png') + let patternId = 'pattern' + (++counter) + let patternNode = defs.append('pattern') + patternNode.attr('id', patternId) + .attr('width', width) + .attr('height', height) + .attr('patternUnits', 'userSpaceOnUse') + patternNode.append('image') + .attr('href', imgSrc) + .attr('x', 0) + .attr('y', 0) + .attr('width', width) + .attr('height', height) + if (params) { + let transform = [] + if (params.scaleX && params.scaleY) { + transform.push(`scale(${params.scaleX},${params.scaleY})`) + } + if (transform.length > 0) { + patternNode.attr('patternTransform', transform.join(' ')) + } + } + return `url(#${patternId})` + } + } + + function texturePattern(patternNode, img, texture, anchor) { + let width = anchor[2] + let height = anchor[3] + if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { + width = img.width + height = img.height + } + if (texture.alignment || !texture.stretch) { + // 图片平铺 + width = img.width + height = img.height + } + patternNode.attr('width', width).attr('height', height) + let patternCanvas = document.createElement('canvas') + patternCanvas.width = Math.max(1, width) + patternCanvas.height = Math.max(1, height) + let patternCtx = patternCanvas.getContext('2d') + patternCtx.imageSmoothingEnabled = true + patternCtx.imageSmoothingQuality = 'high' + if (texture.alpha >= 0 && texture.alpha < 100000) { + patternCtx.globalAlpha = texture.alpha / 100000 + } + let imgInsets = null + if (texture.insets) { + let top = texture.insets[0] / 100000 + let left = texture.insets[1] / 100000 + let bottom = texture.insets[2] / 100000 + let right = texture.insets[3] / 100000 + let x = img.width * left + let y = img.height * top + let w = img.width * (1 - left - right) + let h = img.height * (1 - top - bottom) + imgInsets = [x, y, w, h] + } + if (texture.stretch) { + let top = texture.stretch[0] / 100000 + let left = texture.stretch[1] / 100000 + let bottom = texture.stretch[2] / 100000 + let right = texture.stretch[3] / 100000 + let x = width * left + let y = height * top + let w = width * (1 - left - right) + let h = height * (1 - top - bottom) + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) + } else { + patternCtx.drawImage(img, x, y, w, h) + } + } else if (texture.alignment) { + let x = 0, y = 0, scale = zoom + if (texture.alignment == 'CENTER') { + if (width > anchor[2] / scale) { + x = (width - anchor[2] / scale) / 2 + } + if (height > anchor[3] / scale) { + y = (height - anchor[3] / scale) / 2 + } + } + if (!x && !y) { + scale = Math.max(scale, 1) + } + patternCtx.drawImage(img, x, y, width, height, 0, 0, width * scale, height * scale) + } else { + if (imgInsets) { + patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) + } else { + patternCtx.drawImage(img, 0, 0, width, height) + } + } + if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { + try { + // 重新着色 + let color = texture.duoTone[0].realColor + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) + let data = imageData.data + for(var i = 0; i < data.length; i += 4) { + let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 + // black / white + let prst = texture.duoTonePrst == 'white' ? 255 : 0 + data[i] = gray * r + (1 - gray) * prst + data[i + 1] = gray * g + (1 - gray) * prst + data[i + 2] = gray * b + (1 - gray) * prst + } + patternCtx.putImageData(imageData, 0, 0) + } catch(e) { /* empty */ } + } + // let mode = texture.alignment ? 'repeat' : 'no-repeat' + let imgSrc = patternCanvas.toDataURL('image/png') + patternNode.append('image') + .attr('href', imgSrc) + .attr('x', 0) + .attr('y', 0) + .attr('width', width) + .attr('height', height) + } + + function toColor(colorObj, defaultColor) { + if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { + return defaultColor || 'transparent' + } + let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color + let r = (color >> 16) & 255 + let g = (color >> 8) & 255 + let b = (color >> 0) & 255 + let a = ((color >> 24) & 255) / 255 + if (colorObj.realColor == null) { + if (colorObj.alpha != null && colorObj.alpha != -1) { + if (colorObj.alpha > 1000) { + a = colorObj.alpha / 100000 + } else { + a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 + } + a = Math.min(1, Math.max(0, a)) + } + if (colorObj.lumMod && colorObj.lumMod > 0) { + let value = colorObj.lumMod / 100000 + r = r * value + g = g * value + b = b * value + } + if (colorObj.lumOff && colorObj.lumOff > 0) { + let value = colorObj.lumOff / 100000 + r += 255 * value + g += 255 * value + b += 255 * value + } + } + return `rgba(${r}, ${g}, ${b}, ${a})` + } + + function toColorValue(r, g, b, a) { + a = (a == null ? 255 : a) + return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 + } + + function text(obj) { + if (obj == null) { + return null + } + let text = obj.text + if (text != null) { + return text + } + if (obj.children != null && obj.children.length > 0) { + let textAll = '' + for (let i = 0; i < obj.children.length; i++) { + let p = obj.children[i] + if (p.children == null) { + continue + } + let pText = '' + for (let j = 0; j < p.children.length; j++) { + let r = p.children[j] + if (r.text == null) { + continue + } + pText += r.text + } + if (pText) { + textAll += (pText + '\n') + } + } + if (textAll.length > 0) { + textAll = textAll.substring(0, textAll.length - 1) + } + return textAll + } + return '' + } + + function loadImage(src) { + return new Promise(resolve => { + if (!src) { + resolve() + return + } + let cacheKey + if (src.length < 15) { + cacheKey = src + } else { + cacheKey = src.length + '_' + src.substring(src.length - 15) + } + let img = imageCache[cacheKey] + if (img == null) { + img = new Image() + let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) + if (!eqOrigin) { + img.crossOrigin = 'anonymous' + } + img.src = src + img.onload = function() { + imageCache[cacheKey] = img + resolve(img) + } + img.onerror = function (e) { + resolve() + console.log('图片加载失败: ', src, e) + } + } else { + resolve(img) + } + }) + } + + function calcPointList(page) { + pointList = [] + recursion(page.children, c => { + if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { + let point = scaleAnchor(c.point) + if (!point) { + point = scaleAnchor(c.extInfo.property.anchor) + } + let _point + if (point[2] < 0.1) { + let width = scaleValue((c.extInfo.property.strokeStyle || {}).lineWidth || 1) + let x = point[0] - width / 2 + _point = { x: x, endX: x + width, y: point[1], endY: point[1] + point[3], sort: width + point[3], obj: c } + } else if (point[3] < 0.1) { + let height = scaleValue((c.extInfo.property.strokeStyle || {}).lineWidth || 1) + let y = point[1] - height / 2 + _point = { x: point[0], endX: point[0] + point[2], y: y, endY: y + height, sort: point[2] + height, obj: c } + } else { + _point = { x: point[0], endX: point[0] + point[2], y: point[1], endY: point[1] + point[3], sort: point[2] + point[3], obj: c } + } + pointList.push(_point) + } + }) + pointList.sort((p1, p2) => p1.sort > p2.sort ? 1 : -1) + } + + function removePoint() { + if (currentPoint && currentPoint.obj && (!currentSelect || currentPoint.obj.id != currentSelect.id)) { + let gNode = document.getElementById('g-' + currentPoint.obj.id) + if (gNode) { + gNode.style.cursor = null + gNode.style.outline = null + } + } + currentPoint = null + } + + function showPoint(point) { + removePoint() + currentPoint = point + let gNode = document.getElementById('g-' + currentPoint.obj.id) + if (gNode && (!currentSelect || currentPoint.obj.id != currentSelect.id)) { + gNode.style.cursor = 'move' + gNode.style.outline = '1px dashed #777' + } + } + + function addElementEvent(gNode, elementObj) { + let node = gNode.node() + node.addEventListener('click', function (e) { + if (currentPoint && currentSelect && currentPoint.obj.id == currentSelect.id) { + if (!document.getElementById('move_element_operate')) { + addElementMoveScale(elementObj) + } + return + } + if (currentPoint && currentPoint.obj.id != elementObj.id && (currentPoint.obj.type == 'text' || currentPoint.obj.type == 'freeform')) { + // 文本被遮挡处理 + let rId = null + for (let i = 0; i < currentPoint.obj.children.length; i++) { + let p = currentPoint.obj.children[i] + for (let j = 0; j < p.children.length; j++) { + let r = p.children[j] + let rNode = document.getElementById(r.id) + let rect = rNode.getBoundingClientRect() + if (e.clientX >= rect.x && e.clientX <= rect.x + rect.width && e.clientY >= rect.y && e.clientY <= rect.y + rect.height) { + rId = r.id + if (r.text && r.text.trim()) { + break + } + } + } + if (rId) { + break + } + } + if (rId) { + editRunText(rId, currentPoint.obj) + e.cancelBubble = true + return + } + } + if (currentPoint && currentPoint.obj.id != elementObj.id) { + addElementMoveScale(elementObj) + } else if (!currentPoint) { + removeElementMoveScale() + } + }) + node.addEventListener('mousedown', function (e) { + if (!currentPoint) { + return + } + if (!currentSelect || currentPoint.obj.id != currentSelect.id) { + addElementMoveScale(currentPoint.obj) + } + doElementMove(e, currentPoint.obj) + }) + } + + function addRunTextEvent(rNode, textObj) { + let rId = rNode.attr('id') + let node = rNode.node() + // node.addEventListener('mouseenter', function () { + // node.style.outline = '1px dashed #f35858' + // }) + // node.addEventListener('mouseleave', function () { + // node.style.outline = null + // }) + node.addEventListener('click', function (e) { + editRunText(rId, textObj) + e.cancelBubble = true + }) + } + + function doElementMove(e, obj) { + // 移动 + if (obj.type == 'tableColumn') { + // table + obj = idMap[idMap[obj.pid].pid] + } + if (!obj.point) { + return + } + let gNode = document.getElementById('g-' + obj.id) + if (!gNode) { + return + } + let x = e.clientX + let y = e.clientY + let g = d3.select(gNode) + let flipX = parseInt(g.attr('groupFlipX') || 1) + let flipY = parseInt(g.attr('groupFlipY') || 1) + let lastTranslate = g.translate() + let translateX = lastTranslate.x + let translateY = lastTranslate.y + let updateAnchor = (obj, tx, ty) => { + let point = obj.point + point[0] = point[0] + tx * flipX + point[1] = point[1] + ty * flipY + let anchor = obj.extInfo.property.anchor + if (point !== anchor) { + anchor[0] = anchor[0] + tx * (anchor[2] / point[2]) + anchor[1] = anchor[1] + ty * (anchor[3] / point[3]) + } + let interiorAnchor = obj.extInfo.property.interiorAnchor + if (interiorAnchor) { + interiorAnchor[0] = interiorAnchor[0] + tx * (interiorAnchor[2] / point[2]) + interiorAnchor[1] = interiorAnchor[1] + ty * (interiorAnchor[3] / point[3]) + } + if (obj.type == 'table') { + let rows = obj.children || [] + for (let i = 0; i < rows.length; i++) { + let columns = rows[i].children || [] + for (let j = 0; j < columns.length; j++) { + let columnAnchor = columns[j].extInfo.property.anchor + columnAnchor[0] = columnAnchor[0] + tx + columnAnchor[1] = columnAnchor[1] + ty + } + } + } + } + let rotate = g.rotate() + let move_element_operate = document.getElementById('move_element_operate') + let tx = 0, ty = 0 + let lastMoveX = +(g.attr('moveX') || 0) + let lastMoveY = +(g.attr('moveY') || 0) + document.onmousemove = function (e2) { + tx = (e2.clientX - x) * flipX + ty = (e2.clientY - y) * flipY + if (move_element_operate) { + move_element_operate.remove() + move_element_operate = null + currentSelect = null + } + if (rotate) { + g.rotate(0) + } + g.translate(translateX + tx, translateY + ty) + } + let cursor = g.style('cursor') + g.style('cursor', 'move') + document.onmouseup = function (e2) { + g.style('cursor', cursor) + document.onmousemove = null + document.onmouseup = null + if (rotate) { + g.rotate(rotate.rotate, rotate.x, rotate.y) + } + if (tx || ty) { + const real_tx = tx / zoom + const real_ty = ty / zoom + updateAnchor(obj, real_tx, real_ty) + if (obj != idMap[obj.id]) { + updateAnchor(idMap[obj.id], real_tx, real_ty) + } + g.attr('moveX', lastMoveX + tx) + g.attr('moveY', lastMoveY + ty) + // 重新渲染元素 + // $this.redrawElementWithId(obj.id) + // 不重新渲染,重新计算元素位置 + page && calcPointList(page) + if ($this.onchange) { + $this.onchange(page, 'move', obj, e2) + } + } + setTimeout(() => addElementMoveScale(obj), 10) + } + } + + function doElementRotate(e, obj) { + // 旋转 + if (obj.type == 'tableColumn') { + // table + obj = idMap[idMap[obj.pid].pid] + } + if (!obj.point) { + return + } + let gNode = document.getElementById('g-' + obj.id) + if (!gNode) { + return + } + let g = d3.select(gNode) + let flipX = parseInt(g.attr('groupFlipX') || 1) + let flipY = parseInt(g.attr('groupFlipY') || 1) + let rotate = g.rotate() + if (!rotate.rotate && !rotate.x) { + let anchor = scaleAnchor(obj.extInfo?.property?.anchor ? obj.extInfo.property.anchor : obj.point) + let interior = g.attr('interior') + if (interior) { + interior = JSON.parse(interior) + anchor = [anchor[0] * interior.scaleX + interior.tx * zoom, anchor[1] * interior.scaleY + interior.ty * zoom, anchor[2] * interior.scaleX, anchor[3] * interior.scaleY] + } + let cx = anchor[0] + anchor[2] / 2 + let cy = anchor[1] + anchor[3] / 2 + rotate = { rotate: 0, x: cx, y: cy, interior: true } + } + let rect = gNode.getBoundingClientRect() + let centerX = rect.x + rect.width / 2 + let centerY = rect.y + rect.height / 2 + let startAngle = Math.atan2(e.clientY - centerY, e.clientX - centerX) * 180 / Math.PI - rotate.rotate + let updateRotate = (obj, angle) => { + obj.extInfo.property.rotation = angle + } + let angle = 0 + let move_rotate_span = document.createElement('span') + move_rotate_span.id = 'move_rotate_span' + move_rotate_span.style.fontSize = '14px' + move_rotate_span.style.color = '#5f6063' + move_rotate_span.style.position = 'fixed' + move_rotate_span.style.left = e.clientX + 'px' + move_rotate_span.style.top = e.clientY + 'px' + move_rotate_span.style.margin = '-20px 0px 0px 12px' + move_rotate_span.innerText = rotate.rotate.toFixed(0) + '°' + document.body.appendChild(move_rotate_span) + let move_element_operate = document.getElementById('move_element_operate') + document.onmousemove = function (e2) { + if (move_element_operate) { + move_element_operate.remove() + move_element_operate = null + currentSelect = null + } + let endAngle = Math.atan2(e2.clientY - centerY, e2.clientX - centerX) * 180 / Math.PI + angle = (endAngle - startAngle) % 360 * flipX + angle = +(angle < 0 ? angle + 360 : angle).toFixed(0) + g.rotate(angle, rotate.x, rotate.y) + move_rotate_span.style.left = e2.clientX + 'px' + move_rotate_span.style.top = e2.clientY + 'px' + move_rotate_span.innerText = angle + '°' + } + document.onmouseup = function (e2) { + document.onmousemove = null + document.onmouseup = null + move_rotate_span.remove() + if (angle) { + updateRotate(obj, angle) + if (obj != idMap[obj.id]) { + updateRotate(idMap[obj.id], angle) + } + if (rotate.interior) { + // 重新渲染元素 + $this.redrawElementWithId(obj.id) + } else { + // 不重新渲染,重新计算元素位置 + page && calcPointList(page) + setTimeout(() => addElementMoveScale(obj), 10) + } + if ($this.onchange) { + $this.onchange(page, 'rotate', obj, e2) + } + } else { + setTimeout(() => addElementMoveScale(obj), 10) + } + } + } + + function rotatePoint(pointX, pointY, centerX, centerY, angle) { + angle = angle * Math.PI / 180 + let rotatedX = Math.cos(angle) * (pointX - centerX) - Math.sin(angle) * (pointY - centerY) + centerX + let rotatedY = Math.sin(angle) * (pointX - centerX) + Math.cos(angle) * (pointY - centerY) + centerY + return [rotatedX, rotatedY] + } + + function addElementMoveScale(elementObj) { + removeElementMoveScale() + if (!elementObj) { + return + } + if (!elementObj.point || elementObj.type == 'tableColumn') { + return + } + let gNode = document.getElementById('g-' + elementObj.id) + if (!gNode) { + return + } + console.log('obj', elementObj) + let g = d3.select(gNode) + currentSelect = elementObj + // gNode.style.outline = '1px dashed #f35858' + let isText = (elementObj.type == 'text' || elementObj.type == 'freeform') && elementObj.children && elementObj.children.length > 0 + if (isText) { + let hasRs = false + for (let i = 0; i < elementObj.children.length; i++) { + if (elementObj.children[i].children && elementObj.children[i].children.length > 0) { + hasRs = true + break + } + } + isText = hasRs + } + let svgNode = svg.node() + let svgRect = svgNode.getClientRects()[0] + let x = svgRect.x + elementObj.point[0] * zoom + let y = svgRect.y + elementObj.point[1] * zoom + let width = elementObj.point[2] * zoom + let height = elementObj.point[3] * zoom + let moveElements = [ + { left: '0px', top: '0px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nwse-resize' }, + { left: width / 2 + 'px', top: '0px', width: '16px', height: '8px', margin: '-4px 0px 0px -8px', cursor: 'ns-resize' }, + { left: width + 'px', top: '0px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nesw-resize' }, + { left: width + 'px', top: height / 2 + 'px', width: '8px', height: '16px', margin: '-8px 0px 0px -4px', cursor: 'ew-resize' }, + { left: width + 'px', top: height + 'px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nwse-resize' }, + { left: width / 2 + 'px', top: height + 'px', width: '16px', height: '8px', margin: '-4px 0px 0px -8px', cursor: 'ns-resize' }, + { left: '0px', top: height + 'px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nesw-resize' }, + { left: '0px', top: height / 2 + 'px', width: '8px', height: '16px', margin: '-8px 0px 0px -4px', cursor: 'ew-resize' } + ] + let div = document.createElement('div') + div.id = 'move_element_operate' + div.style.zIndex = 9999 + div.style.position = 'fixed' + div.style.userSelect = 'none' + div.style.pointerEvents = 'none' + div.style.left = x + 'px' + div.style.top = y + 'px' + div.style.width = width + 'px' + div.style.height = height + 'px' + div.style.outline = '1px dashed #f35858' + let rotate = g.rotate().rotate + if (rotate) { + div.style.transform = `rotate(${rotate}deg)` + } + for (let i = 0; i < moveElements.length; i++) { + if (isText && (i == 1 || i == 5)) { + continue + } + let obj = moveElements[i] + let span = document.createElement('span') + span.id = 'move_span_' + i + span.style.pointerEvents = 'all' + span.style.position = 'absolute' + span.style.background = '#fff' + span.style.borderRadius = '5px' + span.style.border = '1px solid #a1a4ad' + span.style.left = obj.left + span.style.top = obj.top + span.style.width = obj.width + span.style.height = obj.height + span.style.cursor = obj.cursor + span.style.margin = obj.margin + span.addEventListener('mousedown', function (e) { + // 缩放 + doElementMoveScale(e, elementObj, i) + }) + div.appendChild(span) + } + let img = document.createElement('img') + img.id = 'move_rotate_img' + img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkNFRjkzREQyQUVBRDExRUE5RDkwQTZCNzUwQUEwQkI5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkNFRjkzREQzQUVBRDExRUE5RDkwQTZCNzUwQUEwQkI5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6Q0VGOTNERDBBRUFEMTFFQTlEOTBBNkI3NTBBQTBCQjkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6Q0VGOTNERDFBRUFEMTFFQTlEOTBBNkI3NTBBQTBCQjkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6qKiSpAAACtElEQVR42pRUX2iSURQ/3/4Qpc6EHipKrdwcGOxlDCsI11gPbWt/zCnR2GqNELZRsJ4qG8Sgh+qlxmJREQS1VUTSgiLIoMXoUQVJ9segsIf56cypn06/zrG78WlEeuD3ne/cc+/vnnPuuZcTRREkYkbYEROIF1CEtLQe3/gvk4xfiERWnp/s6WtihHIoUSrWiZYC326d7h+AxaUAhMPhpsrKyl9yuTyFvjBiHjGHmEZ8+RcZx9L0m5qOViMhfA/Mg1KphHQ6DalUClQqFeh0OjAajdDd3Q0NDQ1TrAwf/0oTDQ4XTt6fvAsatRp2aXXA8zxEo9FVFPB4PDA2NgYKhQKsVivYbDYrznfhWnVhZFQzrqPTPFGlrLr26uUzOHTwACSSyc+tbe01w8Pnd3yandVrtdq2kZGL130+H8RiMXA4HMDqmp/msZa2ctQyxLbRUYe5Vq+3LCwsPrl0+YoTx6hmIkN2/M7tIzLZlscGgwHcbjeVYGeX2RKUklF0mxEqRBU7lDhiFZGmOSwDGuemp57eGBoatNbX14Pdbh/EDMalaYpsUYydHI9YYWTxAqzxfGjOZDKBy+UCPLxGttkfspnXznUymhxhZFEiQ18hWSIY/Ompq6sDr9cLHMftzyOjj4RQQCTZf3bdh8iw+glf/f5FjUYDwWCuVNvzGp/6rFgIgmBJp9c+ZLNZEaMSSTKZzDtU7Vj7vOv0X8Fbca73zFmTVlcLu/dUg2afHvr6B5o32qTYqHBnjiJbDoXEw43NonpvTU6TjU3cSf5SIuM6u044yzju6qOH93K3hTTZ7R1db8hfVuLDUH6qp/cBRnrz/duZH6TJpnHpRS/m3aKNNyG2sganRk+w3qSWEipKiIp2zTCCctZCKWavkb/oNAuam6JZZjpeMlkBYYJdtwSzc7X6LcAAZxVxcQ2YXyMAAAAASUVORK5CYII=' + img.style.pointerEvents = 'all' + img.style.position = 'absolute' + img.style.left = width + 'px' + img.style.top = '0px' + img.style.width = '20px' + img.style.height = '20px' + img.style.margin = '-15px 0px 0px 0px' + img.style.cursor = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABWUlEQVQ4T6WT0U3DQAyGf/sGoBuQDcjp7p2wQTsBbNCOABMAE5BuwAjpe09XJqAjlAFyRq5yIUkRKuCXSIn92f79h/DPoGl9jLFIKS0BzAEU+l1EdgBqY8zaWnvQnLZtS+/96wgQQrgD8PLDUHsADwAeAbw556oeMCwWkQ8iqpn5NaVUikhJRLcT8KYHdGO/dwkbZp7rqMOCEMKq65xffwFCCE8AltrZGFNMi7sGEcBsAB0BdLdLAM/OOe00ihhjlVK6n7yunXP1UYMQguiTmW+stc1vLjsCiMhCT/MXgN75SkTW3ns95dmRJ+gVZmZrrVXgSWy327kxphmKfATEGGcpJS1SIQ/MvJhqkc+orvTe20zvjRRjLNu2bYjoItuXiBoRKYiozLZWBzJzlacYWVkhKSX1xPV3K6hGxpjVyQrTZN2161qJyJ6Idmpra636ZRQnf+PZ8neJn9q+rxFGGvPWAAAAAElFTkSuQmCC) 8 8,default' + img.addEventListener('mousedown', function (e) { + // 旋转 + doElementRotate(e, elementObj) + }) + div.appendChild(img) + document.body.appendChild(div) + if ($this.onselect) { + $this.onselect(page, elementObj) + } + } + + function removeElementMoveScale() { + let gNode = currentSelect ? document.getElementById('g-' + currentSelect.id) : null + if (gNode) { + gNode.style.outline = null + } + currentSelect = null + let element = document.getElementById('move_element_operate') + element && element.remove() + if ($this.onunselect) { + $this.onunselect(page) + } + } + + function doElementMoveScale(e, obj, idx) { + // 移动缩放 + if (obj.type == 'tableColumn') { + // table + obj = idMap[idMap[obj.pid].pid] + } + if (!obj.point) { + return + } + let gNode = document.getElementById('g-' + obj.id) + if (!gNode) { + return + } + let x = obj.point[0] * zoom + let y = obj.point[1] * zoom + let width = obj.point[2] * zoom + let height = obj.point[3] * zoom + let clientX = e.clientX + let clientY = e.clientY + let g = d3.select(gNode) + let lastScale = g.scale() + let scaleX = lastScale.x + let scaleY = lastScale.y + let rect = gNode.getBoundingClientRect() + let centerX = rect.x + rect.width / 2 + let centerY = rect.y + rect.height / 2 + let lastRotate = g.rotate() + if (lastRotate.rotate) { + let clientXY = rotatePoint(clientX, clientY, centerX, centerY, -lastRotate.rotate) + clientX = clientXY[0] + clientY = clientXY[1] + } + let lastTranslate = g.translate() + let translateX = lastTranslate.x + let translateY = lastTranslate.y + let changeData = { tx: 0, ty: 0, scaleX: 1, scaleY: 1 } + let changeElement = (tx, ty) => { + let _scaleX = 1, _scaleY = 1 + let originalWidth = width / scaleX + let originalHeight = height / scaleY + let lastTx, originalX, newTx, newScaleX, originalTranslateX + let lastTy, originalY, newTy, newScaleY, originalTranslateY + switch (idx) { + case 0: + // 左上角 + _scaleX = (width - tx) / width + _scaleY = (height - ty) / height + if (_scaleX < 0.15 || _scaleY < 0.15) { + return false + } + changeData.tx = tx + changeData.ty = ty + changeData.scaleX = _scaleX + changeData.scaleY = _scaleY + // g.translate(translateX + tx + x * (1 - _scaleX), translateY + ty + y * (1 - _scaleY)) + // g.scale(scaleX * _scaleX, scaleY * _scaleY) + lastTx = originalWidth - width + originalX = x - lastTx + newTx = x - originalX + tx + newScaleX = (originalWidth - newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + lastTy = originalHeight - height + originalY = y - lastTy + newTy = y - originalY + ty + newScaleY = (originalHeight - newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), originalTranslateY + newTy + originalY * (1 - newScaleY)) + g.scale(newScaleX, newScaleY) + break + case 1: + // 上 + _scaleY = (height - ty) / height + if (_scaleY < 0.15) { + return false + } + changeData.ty = ty + changeData.scaleY = _scaleY + // g.translate(translateX, translateY + ty + y * (1 - _scaleY)) + // g.scale(scaleX, scaleY * _scaleY) + lastTy = originalHeight - height + originalY = y - lastTy + newTy = y - originalY + ty + newScaleY = (originalHeight - newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(translateX, originalTranslateY + newTy + originalY * (1 - newScaleY)) + g.scale(scaleX, newScaleY) + break + case 2: + // 右上角 + _scaleX = (width + tx) / width + _scaleY = (height - ty) / height + if (_scaleX < 0.15 || _scaleY < 0.15) { + return false + } + changeData.ty = ty + changeData.scaleX = _scaleX + changeData.scaleY = _scaleY + // g.translate(translateX + x * (1 - _scaleX), translateY + ty + y * (1 - _scaleY)) + // g.scale(scaleX * _scaleX, scaleY * _scaleY) + lastTx = width - originalWidth + originalX = x + newTx = lastTx + tx + newScaleX = (originalWidth + newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + lastTy = originalHeight - height + originalY = y - lastTy + newTy = y - originalY + ty + newScaleY = (originalHeight - newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(originalTranslateX + originalX * (1 - newScaleX), originalTranslateY + newTy + originalY * (1 - newScaleY)) + g.scale(newScaleX, newScaleY) + break + case 3: + // 右 + _scaleX = (width + tx) / width + if (_scaleX < 0.15) { + return false + } + changeData.scaleX = _scaleX + // g.translate(translateX + x * (1 - _scaleX), translateY) + // g.scale(scaleX * _scaleX, scaleY) + lastTx = width - originalWidth + originalX = x + newTx = lastTx + tx + newScaleX = (originalWidth + newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + g.translate(originalTranslateX + originalX * (1 - newScaleX), translateY) + g.scale(newScaleX, scaleY) + break + case 4: + // 右下角 + _scaleX = (width + tx) / width + _scaleY = (height + ty) / height + if (_scaleX < 0.15 || _scaleY < 0.15) { + return false + } + changeData.scaleX = _scaleX + changeData.scaleY = _scaleY + // g.translate(translateX + x * (1 - _scaleX), translateY + y * (1 - _scaleY)) + // g.scale(scaleX * _scaleX, scaleY * _scaleY) + lastTx = width - originalWidth + originalX = x + newTx = lastTx + tx + newScaleX = (originalWidth + newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + lastTy = height - originalHeight + originalY = y + newTy = lastTy + ty + newScaleY = (originalHeight + newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(originalTranslateX + originalX * (1 - newScaleX), originalTranslateY + originalY * (1 - newScaleY)) + g.scale(newScaleX, newScaleY) + break + case 5: + // 下 + _scaleY = (height + ty) / height + if (_scaleY < 0.15) { + return false + } + changeData.scaleY = _scaleY + // g.translate(translateX, translateY + y * (1 - _scaleY)) + // g.scale(scaleX, scaleY * _scaleY) + lastTy = height - originalHeight + originalY = y + newTy = lastTy + ty + newScaleY = (originalHeight + newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(translateX, originalTranslateY + originalY * (1 - newScaleY)) + g.scale(scaleX, newScaleY) + break + case 6: + // 左下角 + _scaleX = (width - tx) / width + _scaleY = (height + ty) / height + if (_scaleX < 0.15 || _scaleY < 0.15) { + return false + } + changeData.scaleX = _scaleX + changeData.scaleY = _scaleY + changeData.tx = tx + // g.translate(translateX + tx + x * (1 - _scaleX), translateY + y * (1 - _scaleY)) + // g.scale(scaleX * _scaleX, scaleY * _scaleY) + lastTx = originalWidth - width + originalX = x - lastTx + newTx = x - originalX + tx + newScaleX = (originalWidth - newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + lastTy = height - originalHeight + originalY = y + newTy = lastTy + ty + newScaleY = (originalHeight + newTy) / originalHeight + originalTranslateY = +(g.attr('moveY') || 0) * newScaleY + g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), originalTranslateY + originalY * (1 - newScaleY)) + g.scale(newScaleX, newScaleY) + break + case 7: + // 左 + _scaleX = (width - tx) / width + if (_scaleX < 0.15) { + return false + } + changeData.tx = tx + changeData.scaleX = _scaleX + // g.translate(translateX + tx + x * (1 - _scaleX), translateY) + // g.scale(scaleX * _scaleX, scaleY) + lastTx = originalWidth - width + originalX = x - lastTx + newTx = x - originalX + tx + newScaleX = (originalWidth - newTx) / originalWidth + originalTranslateX = +(g.attr('moveX') || 0) * newScaleX + g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), translateY) + g.scale(newScaleX, scaleY) + break + } + return true + } + let updateElement = (obj) => { + let _tx = changeData.tx / zoom + let _ty = changeData.ty / zoom + let point = obj.point + point[0] = point[0] + _tx + point[1] = point[1] + _ty + let _width = point[2] + let _height = point[3] + point[2] = point[2] * changeData.scaleX + point[3] = point[3] * changeData.scaleY + let anchor = obj.extInfo.property.anchor + if (point !== anchor) { + anchor[0] = anchor[0] + _tx * (anchor[2] / _width) + anchor[1] = anchor[1] + _ty * (anchor[3] / _height) + anchor[2] = anchor[2] * changeData.scaleX + anchor[3] = anchor[3] * changeData.scaleY + } + let interiorAnchor = obj.extInfo.property.interiorAnchor + if (interiorAnchor) { + interiorAnchor[0] = interiorAnchor[0] + _tx * (interiorAnchor[2] / point[2]) + interiorAnchor[1] = interiorAnchor[1] + _ty * (interiorAnchor[3] / point[3]) + } + if (obj.type == 'table') { + let rows = obj.children || [] + for (let i = 0; i < rows.length; i++) { + let row_property = rows[i].extInfo.property + row_property.rowHeight *= changeData.scaleY + let columns = rows[i].children || [] + for (let j = 0; j < columns.length; j++) { + let columns_property = columns[j].extInfo.property + columns_property.columnWidth *= changeData.scaleX + let columnAnchor = columns[j].extInfo.property.anchor + columnAnchor[0] = anchor[0] + columns_property.columnWidth * j + (j + 1) * changeData.scaleX + columnAnchor[1] = anchor[1] + row_property.rowHeight * i + (i + 1) * changeData.scaleY + columnAnchor[2] = columns_property.columnWidth + columnAnchor[3] = row_property.rowHeight + } + } + } + } + let move_element_operate = document.getElementById('move_element_operate') + let tx = 0, ty = 0 + document.onmousemove = function (e2) { + let clientX2 = e2.clientX + let clientY2 = e2.clientY + if (lastRotate.rotate) { + let clientXY2 = rotatePoint(clientX2, clientY2, centerX, centerY, -lastRotate.rotate) + clientX2 = clientXY2[0] + clientY2 = clientXY2[1] + } + tx = clientX2 - clientX + ty = clientY2 - clientY + if (move_element_operate) { + move_element_operate.remove() + move_element_operate = null + currentSelect = null + } + let change = changeElement(tx, ty) + if (!change) { + e.preventDefault() + } + } + document.onmouseup = function (e2) { + document.onmousemove = null + document.onmouseup = null + if (tx || ty) { + updateElement(obj) + if (obj != idMap[obj.id]) { + updateElement(idMap[obj.id]) + } + // 重新渲染 + // $this.drawPptx(pptx, pageIndex, obj.id) + // 重新渲染元素 + $this.redrawElementWithId(obj.id) + if ($this.onchange) { + $this.onchange(page, 'scale', obj, e2) + } + } else { + addElementMoveScale(obj) + } + } + } + + function editRunText(rId, textObj) { + if (mode != 'edit') { + return + } + let obj = idMap[rId] + if (obj == null) { + // ignore master element + return + } + addElementMoveScale(textObj) + let rect = null + let nodeStyle = null + let nodes = document.querySelectorAll(`tspan[id='${rId}']`) + for (let i = 0; i < nodes.length; i++) { + let _rect = nodes[i].getBoundingClientRect() + if (_rect.width == 0 || _rect.height == 0) { + continue + } + if (rect == null) { + rect = { x: _rect.x, y: _rect.y, endX: _rect.x + _rect.width, endY: _rect.y + _rect.height } + nodeStyle = window.getComputedStyle(nodes[i]) + } else { + rect.x = Math.min(rect.x, _rect.x) + rect.y = Math.min(rect.y, _rect.y) + rect.endX = Math.max(rect.endX, _rect.x + _rect.width) + rect.endY = Math.max(rect.endY, _rect.y + _rect.height) + } + } + if (rect == null) { + return + } + rect.width = rect.endX - rect.x + rect.height = rect.endY - rect.y + let fontSize = +nodeStyle.fontSize.replace('px', '') + let textarea = document.getElementById('textarea_' + rId) + if (textarea) { + textarea.remove() + } + textarea = document.createElement('textarea') + textarea.id = 'textarea_' + rId + textarea.style.position = 'absolute' + textarea.style.background = 'none' + textarea.style.border = 'none' + textarea.style.padding = '0' + textarea.style.margin = '0' + textarea.style.resize = 'none' + textarea.style.overflow = 'hidden' + textarea.style.outline = 'none' + textarea.style.zIndex = 999 + let scrollY = window.scrollY || document.documentElement.scrollTop + let scrollX = window.scrollX || document.documentElement.scrollLeft + textarea.style.left = (rect.x + scrollX) + 'px' + textarea.style.top = (rect.y + scrollY) + 'px' + let textWordWrap = textObj.extInfo.property.textWordWrap ?? true + textarea.style.width = Math.max(scaleValue(textObj.point[2]) || rect.width, fontSize) + 'px' + textarea.style.height = Math.max(scaleValue(textObj.point[3]) || rect.height, fontSize) + 'px' + let rotation = (textObj.extInfo.property || {}).rotation + if (rotation) { + textarea.style.transformOrigin = 'center' + textarea.style.transform = 'rotate(' + rotation + 'deg)' + } + if (nodeStyle.fill && nodeStyle.fill.startsWith('rgb')) { + textarea.style.color = nodeStyle.fill + } + textarea.style.font = nodeStyle.font + textarea.style.fontSize = fontSize + 'px' + let p_property = textObj.children[0]?.extInfo.property + // let lineSpacing = p_property.lineSpacing > 0 ? (p_property.lineSpacing / 100) : (1 + Math.abs(p_property.lineSpacing || 0) / 100) + // if (lineSpacing && lineSpacing != 1) { + // textarea.style.lineHeight = lineSpacing + // } + textarea.value = obj.text + nodes.forEach(s => s.style.visibility = 'hidden') + document.body.appendChild(textarea) + textarea.addEventListener('blur', function () { + if (obj.text == textarea.value) { + textarea.remove() + nodes.forEach(s => s.style.visibility = null) + return + } + obj.text = textarea.value + recursion(textObj.children, c => { + if (c.id == rId) { + c.text = obj.text + } + }) + textarea.remove() + let gNode = document.getElementById('g-' + textObj.id) + let g = d3.select(gNode) + drawTextWithG(g, textObj) + if ($this.onchange) { + $this.onchange(textObj) + } + }) + textarea.addEventListener('focus', function () { + if (textarea.scrollHeight > textarea.clientHeight) { + if (textWordWrap) { + textarea.style.height = textarea.scrollHeight + 'px' + } else { + textarea.style.width = textarea.clientWidth + fontSize + 'px' + } + } else if (textarea.scrollWidth > textarea.clientWidth) { + if (textWordWrap) { + textarea.style.height = textarea.clientWidth + fontSize + 'px' + } else { + textarea.style.width = textarea.scrollWidth + 'px' + } + } + }) + textarea.addEventListener('input', function () { + if (textarea.scrollHeight > textarea.clientHeight) { + if (textWordWrap) { + textarea.style.height = textarea.scrollHeight + 'px' + if (textObj.extInfo.property.textVerticalAlignment == 'BOTTOM') { + textarea.style.top = +textarea.style.top.replace('px', '') - fontSize + 'px' + } else if (textObj.extInfo.property.textVerticalAlignment == 'MIDDLE') { + textarea.style.top = +textarea.style.top.replace('px', '') - fontSize / 2 + 'px' + } + } else { + textarea.style.width = textarea.clientWidth + fontSize + 'px' + if (p_property.textAlign == 'RIGHT') { + textarea.style.left = +textarea.style.left.replace('px', '') - fontSize + 'px' + } else if (p_property.textAlign == 'CENTER') { + textarea.style.left = +textarea.style.left.replace('px', '') - fontSize / 2 + 'px' + } + } + } else if (textarea.scrollWidth > textarea.clientWidth) { + if (!textWordWrap) { + textarea.style.width = textarea.scrollWidth + 'px' + if (p_property.textAlign == 'RIGHT') { + textarea.style.left = +textarea.style.left.replace('px', '') - fontSize + 'px' + } else if (p_property.textAlign == 'CENTER') { + textarea.style.left = +textarea.style.left.replace('px', '') - fontSize / 2 + 'px' + } + } + } + }) + textarea.focus() + } + + this.idMap = idMap + this.recursion = recursion + this.drawGeometry = drawGeometry + this.drawElement = drawElement + this.toPaint = toPaint + this.toColor = toColor + this.toColorValue = toColorValue + this.loadImage = loadImage + this.text = text + this.scaleValue = scaleValue + this.showPoint = showPoint + this.removePoint = removePoint + this.addElementMoveScale = addElementMoveScale + this.removeElementMoveScale = removeElementMoveScale + + d3.addEventListener('document', 'mousemove', function(event) { + if (!pptx) { + removePoint() + return + } + let svgNode = svg.node() + let svgRect = svgNode.getClientRects()[0] + if (!svgRect) { + return + } + let clientX = event.clientX + let clientY = event.clientY + if (!(clientX >= svgRect.x && clientX <= svgRect.x + svgRect.width && clientY >= svgRect.y && clientY <= svgRect.y + svgRect.height)) { + removePoint() + return + } + let offsetX = clientX - svgRect.x + let offsetY = clientY - svgRect.y + mTimer && clearTimeout(mTimer) + mTimer = setTimeout(() => { + let newPointList = [] + for (let i = 0; i < pointList.length; i++) { + let point = pointList[i] + if (offsetX >= point.x && offsetX <= point.endX && offsetY >= point.y && offsetY <= point.endY) { + // if (currentPoint == point) return + // showPoint(point) + // return + newPointList.push(point) + } + } + if (newPointList.length > 0) { + newPointList.sort((p1, p2) => { + let text1 = p1.obj.type == 'text' || p1.obj.type == 'freeform' + let text2 = p2.obj.type == 'text' || p2.obj.type == 'freeform' + if (!text1 && !text2) { + return 0 + } + let s1 = text(p1.obj) + let s2 = text(p2.obj) + if (s1 && s2) { + return 0 + } + if (s1) { + return -1 + } + if (s2) { + return 1 + } + return 0 + }) + showPoint(newPointList[0]) + } else { + removePoint() + } + }, 10) + }) + d3.addEventListener('document', 'keydown', function (event) { + if (!currentPoint) { + return + } + let obj = currentPoint.obj + if (!obj.point || obj.type == 'tableColumn') { + return + } + let gNode = document.getElementById('g-' + obj.id) + if (!gNode) { + return + } + if (event.keyCode == 46) { + recursion(page.children, element => { + if (obj.id == element.id) { + const children = element.pid ? idMap[element.pid].children : page.children + for (let i = 0; i < children.length; i++) { + if (children[i].id == element.id) { + children.splice(i, 1) + delete idMap[obj.id] + gNode.remove() + currentPoint = null + removeElementMoveScale() + calcPointList(page) + if ($this.onchange) { + $this.onchange(page, 'delete', obj, event) + } + break + } + } + } + }) + } + }) + d3.addEventListener('window', 'scroll', function() { + removePoint() + removeElementMoveScale() + }) + d3.addEventListener('window', 'resize', function() { + removePoint() + removeElementMoveScale() + page && calcPointList(page) + }) +} + +export { D3Element, d3, Ppt2Svg } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js new file mode 100644 index 0000000..cfb7765 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js @@ -0,0 +1,238 @@ +function SSE(url, options) { + this.INITIALIZING = -1; + this.CONNECTING = 0; + this.OPEN = 1; + this.CLOSED = 2; + + this.url = url; + + options = options || {}; + this.headers = options.headers || {}; + this.payload = options.payload !== undefined ? options.payload : ""; + this.method = options.method || (this.payload && "POST") || "GET"; + this.withCredentials = !!options.withCredentials; + + this.FIELD_SEPARATOR = ":"; + this.listeners = {}; + + this.xhr = null; + this.readyState = this.INITIALIZING; + this.progress = 0; + this.chunk = ""; + + this.addEventListener = function (type, listener) { + if (this.listeners[type] === undefined) { + this.listeners[type] = []; + } + + if (this.listeners[type].indexOf(listener) === -1) { + this.listeners[type].push(listener); + } + }; + + this.removeEventListener = function (type, listener) { + if (this.listeners[type] === undefined) { + return; + } + + var filtered = []; + this.listeners[type].forEach(function (element) { + if (element !== listener) { + filtered.push(element); + } + }); + if (filtered.length === 0) { + delete this.listeners[type]; + } else { + this.listeners[type] = filtered; + } + }; + + this.dispatchEvent = function (e) { + if (!e) { + return true; + } + + e.source = this; + + var onHandler = "on" + e.type; + if (Object.prototype.hasOwnProperty.call(this, onHandler)) { + this[onHandler].call(this, e); + if (e.defaultPrevented) { + return false; + } + } + + if (this.listeners[e.type]) { + return this.listeners[e.type].every(function (callback) { + callback(e); + return !e.defaultPrevented; + }); + } + + return true; + }; + + this._setReadyState = function (state) { + var event = new CustomEvent("readystatechange"); + event.readyState = state; + this.readyState = state; + this.dispatchEvent(event); + }; + + this._onStreamFailure = function (e) { + var event = new CustomEvent("error"); + event.data = e.currentTarget.response; + this.dispatchEvent(event); + this.close(); + }; + + this._onStreamAbort = function () { + this.dispatchEvent(new CustomEvent("abort")); + this.close(); + }; + + this._onStreamProgress = function (e) { + if (!this.xhr) { + return; + } + + if (this.xhr.status !== 200) { + this._onStreamFailure(e); + return; + } + + if (this.readyState == this.CONNECTING) { + this.dispatchEvent(new CustomEvent("open")); + this._setReadyState(this.OPEN); + } + + var data = this.xhr.responseText.substring(this.progress); + this.progress += data.length; + data.split(/(\r\n|\r|\n){2}/g).forEach( + function (part) { + if (part.trim().length === 0) { + this.dispatchEvent(this._parseEventChunk(this.chunk.trim())); + this.chunk = ""; + } else { + this.chunk += part; + } + }.bind(this) + ); + }; + + this._onStreamLoaded = function (e) { + this._onStreamProgress(e); + + // Parse the last chunk. + this.dispatchEvent(this._parseEventChunk(this.chunk)); + this.chunk = ""; + }; + + /** + * Parse a received SSE event chunk into a constructed event object. + */ + this._parseEventChunk = function (chunk) { + if (!chunk || chunk.length === 0) { + return null; + } + + var e = { id: null, retry: null, data: "", event: "message" }; + chunk.split(/\n|\r\n|\r/).forEach( + function (line) { + line = line.trimRight(); + var index = line.indexOf(this.FIELD_SEPARATOR); + if (index <= 0) { + // Line was either empty, or started with a separator and is a comment. + // Either way, ignore. + return; + } + + var field = line.substring(0, index); + if (!(field in e)) { + return; + } + + var value = line.substring(index + 1).trimLeft(); + if (field === "data") { + e[field] += value; + } else { + e[field] = value; + } + }.bind(this) + ); + + var event = new CustomEvent(e.event); + event.data = e.data; + event.id = e.id; + return event; + }; + + this._checkStreamClosed = function () { + if (!this.xhr) { + return; + } + + if (this.xhr.readyState === XMLHttpRequest.DONE) { + this._setReadyState(this.CLOSED); + var event = new CustomEvent("end"); + event.data = this.xhr.responseText; + this.dispatchEvent(event); + } + }; + + this.stream = function () { + this._setReadyState(this.CONNECTING); + + this.xhr = new XMLHttpRequest(); + this.xhr.addEventListener("progress", this._onStreamProgress.bind(this)); + this.xhr.addEventListener("load", this._onStreamLoaded.bind(this)); + this.xhr.addEventListener( + "readystatechange", + this._checkStreamClosed.bind(this) + ); + this.xhr.addEventListener("error", this._onStreamFailure.bind(this)); + this.xhr.addEventListener("abort", this._onStreamAbort.bind(this)); + this.xhr.open(this.method, this.url); + for (var header in this.headers) { + this.xhr.setRequestHeader(header, this.headers[header]); + } + this.xhr.withCredentials = this.withCredentials; + this.xhr.send(this.payload); + }; + + this.close = function () { + if (this.readyState === this.CLOSED) { + return; + } + + this.xhr.abort(); + this.xhr = null; + this._setReadyState(this.CLOSED); + }; +} + +export { SSE }; + +/* +const url = 'https://xxx/chat'; +var source = new SSE(url, { + method: 'POST', + // withCredentials: true, + headers: { + 'Content-Type': 'application/json', + 'Cache-Control': 'no-cache' + }, + payload: JSON.stringify({ prompt: 'xxx' }), +}); +source.onmessage = function (data) { + console.log('chunk => ' + data.data) +}; +source.onend = function (data) { + console.log('结束'); +}; +source.onerror = function (err) { + console.error('异常', err); +}; +source.stream(); +*/ diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json new file mode 100644 index 0000000..bde5b54 --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json @@ -0,0 +1,16 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "allowJs": true, + "noImplicitAny": false, + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json new file mode 100644 index 0000000..83e5fac --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "compilerOptions": { + "allowJs": true, + "noImplicitAny": false, + "target": "ESNext" + } +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json new file mode 100644 index 0000000..590171b --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json @@ -0,0 +1,21 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "allowJs": true, + "noImplicitAny": false, + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts new file mode 100644 index 0000000..5c45e1d --- /dev/null +++ b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/docs/mockup-ppt-generation.html b/docs/mockup-ppt-generation.html new file mode 100644 index 0000000..4561a99 --- /dev/null +++ b/docs/mockup-ppt-generation.html @@ -0,0 +1,956 @@ + + + + + +PPT生成页面 - 三阶段布局原型 + + + + + + + + + +
+ +
+ + +
+ + +
+

创建你的教学PPT

+

选择模板,输入主题,AI帮你生成专业课件

+ + +
+
+ +
+
+
📎 上传文件
+
🖼️ 上传图片
+
🎤 语音输入
+
📚 选择知识库
+
+ +
+
+
+ + +
+
+
选择模板
+
+
+
+
商务风格
+
简约商务
+
+
+
教育风格
+
活泼教育
+
+
+
科技风格
+
科技蓝
+
+
+
中国风
+
水墨中国
+
+
+
活泼教育
+
法政教育
+
+
+
科技蓝
+
科技蓝
+
+
+
水墨中国
+
水墨中国
+
+
+
+ 更多模板
+
更多模板
+
+
+
+ +
+ + + + + + + +
+ +
+ +
+ + + + + diff --git a/docs/superpowers/plans/2026-03-18-ppt-generation-plan.md b/docs/superpowers/plans/2026-03-18-ppt-generation-plan.md new file mode 100644 index 0000000..8808bd8 --- /dev/null +++ b/docs/superpowers/plans/2026-03-18-ppt-generation-plan.md @@ -0,0 +1,633 @@ +# AI PPT 生成功能实施计划(单次交付版) + +更新时间:2026-03-18 + +> 本计划用于直接指导实现。本计划对应一次性交付版本,不做一期 / 二期拆分;实现顺序可以分步推进,但最终验收必须满足规格文档中的完整能力要求。 + +关联规格: + +- [spec文档.md](/d:/123/AIsystem/docs/superpowers/specs/spec文档.md) + +## 1. 实施原则 + +### 1.1 必须遵守的技术约束 + +- 前端流式方案统一使用 `fetch + reader` +- 不使用原生 `EventSource` +- 不引入 WebSocket 替代 SSE +- 前端不直连 Docmee,统一走后端代理 +- 前端复用 [http.js](/d:/123/AIsystem/teacher-platform/src/api/http.js) 的请求模式 +- 前端入口复用 [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue) +- 预览复用 Docmee 官方 `ppt2svg.js` / `ppt2canvas.js` +- 数据库变更统一使用 Alembic +- LangGraph 只围绕业务主链路落地,不做不必要扩张 + +### 1.2 本次交付目标 + +完成本计划后,用户应能在当前项目中直接完成以下完整链路: + +1. 新建 PPT 会话 +2. 选择知识库与模板 +3. 输入需求并流式生成大纲 +4. 自动配图 +5. 编辑并审批大纲 +6. 生成 PPT 并看到流式进度 +7. 预览、继续修改、元素级编辑 +8. 保存版本并做版本对比 +9. 下载结果 + +## 2. 文件调整方案 + +## 2.1 后端新增文件 + +| 文件 | 作用 | +|------|------| +| `backend/app/models/ppt_session.py` | PPT 会话模型 | +| `backend/app/models/ppt_outline.py` | PPT 大纲版本模型 | +| `backend/app/models/ppt_message.py` | PPT 会话消息模型 | +| `backend/app/models/ppt_result.py` | PPT 结果版本模型 | +| `backend/app/schemas/ppt.py` | PPT 相关请求响应 schema | +| `backend/app/services/ppt/docmee_client.py` | Docmee 代理客户端 | +| `backend/app/services/ppt/image_search.py` | 自动配图服务 | +| `backend/app/services/ppt/state.py` | LangGraph 状态定义 | +| `backend/app/services/ppt/nodes.py` | LangGraph 节点实现 | +| `backend/app/services/ppt/workflow.py` | LangGraph 工作流 | +| `backend/app/services/ppt/serializer.py` | `pptx_property` 解压 / 序列化辅助 | +| `backend/app/api/ppt.py` | PPT API 路由 | +| `backend/alembic/versions/XXXX_add_ppt_tables.py` | 数据库迁移 | + +## 2.2 后端修改文件 + +| 文件 | 变更 | +|------|------| +| `backend/app/models/__init__.py` | 导出新模型 | +| `backend/app/api/__init__.py` | 注册 PPT 路由 | +| `backend/.env.example` | 新增 Docmee / Unsplash 配置 | + +## 2.3 前端新增文件 + +| 文件 | 作用 | +|------|------| +| `teacher-platform/src/api/ppt.js` | PPT API 封装 | +| `teacher-platform/src/components/ppt/PptWorkspace.vue` | PPT 页面主工作区 | +| `teacher-platform/src/components/ppt/PptSidebar.vue` | 会话与版本侧栏 | +| `teacher-platform/src/components/ppt/WelcomePanel.vue` | 欢迎页 | +| `teacher-platform/src/components/ppt/TemplateSelector.vue` | 模板选择器 | +| `teacher-platform/src/components/ppt/KnowledgeLibraryModal.vue` | 知识库选择弹窗 | +| `teacher-platform/src/components/ppt/ChatPanel.vue` | 对话页 | +| `teacher-platform/src/components/ppt/ChatMessage.vue` | 聊天气泡 | +| `teacher-platform/src/components/ppt/OutlineCard.vue` | 大纲卡片 | +| `teacher-platform/src/components/ppt/PptResultCard.vue` | 结果卡片 | +| `teacher-platform/src/components/ppt/PptPreviewPanel.vue` | 预览页 | +| `teacher-platform/src/components/ppt/PptThumbnailList.vue` | 缩略图列表 | +| `teacher-platform/src/components/ppt/PptCanvas.vue` | 大图预览 | +| `teacher-platform/src/components/ppt/PptToolbar.vue` | 顶部工具栏 | +| `teacher-platform/src/components/ppt/PptVersionCompareDialog.vue` | 版本对比弹窗 | +| `teacher-platform/src/components/ppt/ChatInput.vue` | 通用输入框 | +| `teacher-platform/src/utils/ppt2svg.js` | 复用官方渲染器 | +| `teacher-platform/src/utils/ppt2canvas.js` | 复用官方缩略图渲染器 | + +## 2.4 前端修改文件 + +| 文件 | 变更 | +|------|------| +| `teacher-platform/src/views/LessonPrepPpt.vue` | 由占位页面改造成 PPT 功能入口页 | +| `teacher-platform/package.json` | 如确有缺失则补充 `pako` / `base64-js` / Markdown 相关依赖 | + +说明: + +- 不新增新的课前准备 tab +- 不修改 [LessonPrep.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrep.vue) 的导航结构 +- 直接替换当前 `ppt` 页签对应的实现 + +## 3. 实施步骤 + +## Phase 1:数据库与基础模型 + +**目标:** 为会话、大纲版本、消息、结果版本建立稳定数据基础。 + +- [ ] 新建 Alembic 迁移 `XXXX_add_ppt_tables.py` +- [ ] 创建 `ppt_sessions` +- [ ] 创建 `ppt_outlines` +- [ ] 创建 `ppt_messages` +- [ ] 创建 `ppt_results` +- [ ] 为 `ppt_outlines` 和 `ppt_results` 增加 `version`、`is_current` +- [ ] 为 `ppt_results` 增加: + - [ ] `source_pptx_property` + - [ ] `edited_pptx_property` + - [ ] `current_page` + - [ ] `total_pages` +- [ ] 编写对应 SQLAlchemy 模型 +- [ ] 编写 `backend/app/schemas/ppt.py` + +**验证:** + +- [ ] 运行迁移成功 +- [ ] 新模型可被 `Base.metadata` 正确识别 +- [ ] 补充基础 CRUD 测试 + +## Phase 2:Docmee 客户端与模板代理 + +**目标:** 封装 Docmee 的模板、内容生成、PPT 生成、结果加载与下载能力。 + +- [ ] 创建 `backend/app/services/ppt/docmee_client.py` +- [ ] 封装模板列表获取 +- [ ] 封装内容 / 大纲生成 +- [ ] 封装内容更新 +- [ ] 封装 PPT 生成 +- [ ] 封装结果加载 +- [ ] 封装下载地址获取 +- [ ] 封装 `pptx_property` 解压辅助 +- [ ] 所有请求统一由后端读取 `DOCMEE_API_TOKEN` + +**关键要求:** + +- [ ] 前端完全不感知 Docmee token +- [ ] 若主链路采用 V2,但渐进预览需兼容旧接口,兼容逻辑仅存在于后端客户端中 + +**验证:** + +- [ ] 新建 `tests/test_docmee_client.py` +- [ ] mock 成功 / 失败 / 超时场景 +- [ ] 手工验证模板列表与结果加载 + +## Phase 3:自动配图服务 + +**目标:** 在大纲生成完成后自动补充页面配图。 + +- [ ] 创建 `backend/app/services/ppt/image_search.py` +- [ ] 从 Markdown 大纲中提取页面标题 +- [ ] 使用 LLM 翻译关键词 +- [ ] 调用 Unsplash 搜索横版图片 +- [ ] 将结果写入 `ppt_outlines.image_urls` + +**要求:** + +- [ ] 配图失败不阻塞后续审批与生成 +- [ ] 返回空图集时流程仍可继续 + +**验证:** + +- [ ] 新建 `tests/test_image_search.py` +- [ ] 测试大纲解析 +- [ ] 测试关键词翻译 +- [ ] 测试 API 失败兜底 + +## Phase 4:LangGraph 工作流 + +**目标:** 实现服务于业务的生成、审批、修改工作流。 + +- [ ] 创建 `backend/app/services/ppt/state.py` +- [ ] 定义状态字段: + - [ ] `session_id` + - [ ] `user_id` + - [ ] `messages` + - [ ] `selected_library_ids` + - [ ] `template_id` + - [ ] `outline_markdown` + - [ ] `outline_id` + - [ ] `outline_approved` + - [ ] `image_urls` + - [ ] `result_id` + - [ ] `next_action` +- [ ] 创建 `nodes.py` +- [ ] 至少实现以下节点: + - [ ] 检索 / 工具调用 + - [ ] 大纲生成 + - [ ] 自动配图 + - [ ] 审批中断 + - [ ] PPT 生成准备 + - [ ] 修改再生成 +- [ ] 创建 `workflow.py` +- [ ] 编译工作流并支持审批中断恢复 + +**关键要求:** + +- [ ] 工作流必须支持继续修改场景 +- [ ] 工作流复杂度控制在可测试范围内 +- [ ] 不在服务层使用错误的 `async with get_db() as db` 写法 + +**验证:** + +- [ ] 新建 `tests/test_ppt_workflow.py` +- [ ] 测试初次生成 +- [ ] 测试审批恢复 +- [ ] 测试继续修改创建新版本 + +## Phase 5:后端 API 与流式输出 + +**目标:** 提供完整的会话、流式生成、编辑保存、版本查询接口。 + +- [ ] 新建 `backend/app/api/ppt.py` +- [ ] 实现 `GET /ppt/templates` +- [ ] 实现 `POST /ppt/sessions` +- [ ] 实现 `GET /ppt/sessions` +- [ ] 实现 `GET /ppt/sessions/{session_id}` +- [ ] 实现 `POST /ppt/stream/outline` +- [ ] 实现 `POST /ppt/outlines/{outline_id}/approve` +- [ ] 实现 `POST /ppt/stream/generate` +- [ ] 实现 `POST /ppt/results/{result_id}/modify` +- [ ] 实现 `POST /ppt/results/{result_id}/edit-snapshot` +- [ ] 实现 `GET /ppt/results/{result_id}` +- [ ] 实现 `POST /ppt/results/{result_id}/download` +- [ ] 实现 `GET /ppt/sessions/{session_id}/versions` + +### 5.1 流式输出约束 + +- [ ] 所有流式接口统一使用 `StreamingResponse` +- [ ] 统一输出 `data: {"type":"..."}` 的 JSON 事件 +- [ ] 不使用 `event: xxx` 自定义事件名 +- [ ] 事件格式与教案页的流式解析逻辑兼容 + +### 5.2 渐进预览要求 + +- [ ] 若 Docmee 返回页级预览数据,则输出 `page_ready` +- [ ] 若暂时无法页级返回,则至少持续输出 `progress` +- [ ] 最终必须返回完整结果并支持预览恢复 + +**验证:** + +- [ ] 使用 curl / Postman 验证 `text/event-stream` +- [ ] 验证大纲流 +- [ ] 验证 PPT 生成流 +- [ ] 验证错误事件 + +## Phase 6:前端 API 与页面主状态 + +**目标:** 在不引入额外复杂基础设施的前提下,搭建 PPT 页面业务主控。 + +- [ ] 新建 `teacher-platform/src/api/ppt.js` +- [ ] 复用 [http.js](/d:/123/AIsystem/teacher-platform/src/api/http.js) 的请求模式 +- [ ] 封装: + - [ ] 获取模板 + - [ ] 新建会话 + - [ ] 加载会话 + - [ ] 审批大纲 + - [ ] 获取结果 + - [ ] 保存编辑快照 + - [ ] 下载结果 + - [ ] 版本列表 +- [ ] 改造 [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue) 为 PPT 页面根组件 +- [ ] 在根组件中维护: + - [ ] 阶段状态 + - [ ] 当前会话 + - [ ] 消息列表 + - [ ] 当前大纲 + - [ ] 当前模板 + - [ ] 当前结果 + - [ ] 当前版本列表 + - [ ] 当前 `pptxObj` + - [ ] 流式状态 + +### 6.1 前端流式实现 + +- [ ] 参考 [LessonPlanPage.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPlanPage.vue) 实现通用 `streamSSE` +- [ ] 使用 `fetch + reader` +- [ ] 解析 `data:` JSON +- [ ] 根据 `type` 字段分发更新页面状态 + +**验证:** + +- [ ] 根组件能完成一次大纲流式生成 +- [ ] 根组件能完成一次 PPT 生成流式更新 + +## Phase 7:欢迎页与对话页 + +**目标:** 落地 Stage 1 与 Stage 2。 + +- [ ] 创建 `WelcomePanel.vue` +- [ ] 创建 `TemplateSelector.vue` +- [ ] 创建 `KnowledgeLibraryModal.vue` +- [ ] 创建 `ChatPanel.vue` +- [ ] 创建 `ChatMessage.vue` +- [ ] 创建 `OutlineCard.vue` +- [ ] 创建 `PptResultCard.vue` +- [ ] 创建通用 `ChatInput.vue` + +### 7.1 欢迎页要求 + +- [ ] 提供预设卡片 +- [ ] 提供文本输入 +- [ ] 提供模板选择入口 +- [ ] 提供知识库选择入口 + +### 7.2 对话页要求 + +- [ ] 展示消息历史 +- [ ] 展示流式文字 +- [ ] 展示大纲卡片 +- [ ] 支持编辑大纲 +- [ ] 支持审批大纲 +- [ ] 在已有大纲后继续追问 + +**验证:** + +- [ ] 从欢迎页输入需求后可进入对话页 +- [ ] 大纲卡片可编辑并提交 + +## Phase 8:预览页与官方渲染内核接入 + +**目标:** 落地 Stage 3 预览。 + +- [ ] 将官方 `ppt2svg.js` 复制到 `src/utils/` +- [ ] 将官方 `ppt2canvas.js` 复制到 `src/utils/` +- [ ] 处理必要依赖 +- [ ] 创建 `PptCanvas.vue` +- [ ] 创建 `PptThumbnailList.vue` +- [ ] 创建 `PptToolbar.vue` +- [ ] 创建 `PptPreviewPanel.vue` + +### 8.1 预览要求 + +- [ ] 支持缩略图切换 +- [ ] 支持大图预览 +- [ ] 支持窗口 resize +- [ ] 支持从服务端恢复预览 +- [ ] 优先加载 `edited_pptx_property` + +### 8.2 生成中预览要求 + +- [ ] 生成中显示进度 +- [ ] 有 `page_ready` 时更新已完成页 +- [ ] 无 `page_ready` 时仍显示进度与最终完整结果 + +**验证:** + +- [ ] 可正确解压 `pptx_property` +- [ ] 缩略图和大图渲染正常 +- [ ] 刷新后可恢复当前结果 + +## Phase 9:继续修改 PPT 成品 + +**目标:** 在预览阶段支持“继续修改”并生成新版本。 + +- [ ] 在 `PptPreviewPanel.vue` 中保留聊天输入入口 +- [ ] 输入修改指令后调用 `/results/{id}/modify` +- [ ] 后端基于当前大纲 / 当前结果 / 用户指令创建新版本 +- [ ] 前端在生成新版本时更新进度 +- [ ] 新版本完成后更新当前结果并保留旧版本 + +**验证:** + +- [ ] 用户可在预览阶段输入修改指令 +- [ ] 会生成新的 PPT 结果版本 +- [ ] 可在版本列表中切换回旧版本 + +## Phase 10:元素级在线编辑 + +**目标:** 支持预览中的元素级编辑并保存快照。 + +- [ ] 在 `PptCanvas.vue` 中接入官方 edit 模式 +- [ ] 暴露 `onchange` 回调 +- [ ] 在根组件中维护“已编辑未保存”状态 +- [ ] 支持保存编辑快照到后端 +- [ ] 支持刷新后恢复编辑态 + +### 10.1 本次交付最少支持 + +- [ ] 文本编辑 +- [ ] 位置拖拽 +- [ ] 缩放 +- [ ] 旋转 + +### 10.2 保存约束 + +- [ ] 保存时提交最新 `edited_pptx_property` +- [ ] 后端持久化后更新当前结果 + +**验证:** + +- [ ] 编辑文本后刷新仍可恢复 +- [ ] 拖拽、缩放、旋转后保存成功 + +## Phase 11:版本管理与版本对比 + +**目标:** 支持大纲版本与 PPT 结果版本查看、切换、对比。 + +- [ ] 在侧栏中展示会话历史 +- [ ] 在当前会话中展示大纲版本列表 +- [ ] 展示 PPT 结果版本列表 +- [ ] 创建 `PptVersionCompareDialog.vue` +- [ ] 支持选择两个版本做对比 + +### 11.1 对比范围 + +- [ ] 大纲文本内容 +- [ ] 模板与知识库差异 +- [ ] PPT 结果缩略图与元信息 +- [ ] 是否包含元素编辑快照 + +**验证:** + +- [ ] 同一会话中能看到多个版本 +- [ ] 可并排查看两个版本 + +## Phase 12:错误处理与恢复 + +**目标:** 补齐可用性。 + +- [ ] Docmee 接口失败提示 +- [ ] Unsplash 接口失败提示 +- [ ] SSE 中断提示 +- [ ] 权限错误处理 +- [ ] 会话不存在兜底 +- [ ] 生成中禁止重复提交 +- [ ] 页面刷新恢复当前会话 / 当前结果 / 当前编辑态 + +**验证:** + +- [ ] 模拟接口失败 +- [ ] 模拟流中断 +- [ ] 模拟会话恢复 + +## Phase 13:测试 + +**目标:** 关键路径可验证。 + +### 13.1 后端测试 + +- [ ] `tests/test_ppt_models.py` +- [ ] `tests/test_docmee_client.py` +- [ ] `tests/test_image_search.py` +- [ ] `tests/test_ppt_workflow.py` +- [ ] `tests/test_ppt_api.py` + +### 13.2 前端测试 + +- [ ] 流式解析函数测试 +- [ ] `pptx_property` 解压测试 +- [ ] 关键组件渲染测试 + +### 13.3 联调验证 + +- [ ] 创建会话 +- [ ] 生成大纲 +- [ ] 配图 +- [ ] 审批 +- [ ] 生成 PPT +- [ ] 预览 +- [ ] 继续修改 +- [ ] 元素编辑 +- [ ] 版本对比 +- [ ] 下载 + +## Phase 14:文档与交付整理 + +**目标:** 让功能可以被真实使用和维护。 + +- [ ] 更新 README +- [ ] 补充环境变量说明 +- [ ] 写使用说明 +- [ ] 写接口说明 +- [ ] 写部署检查项 + +## 4. 时间评估 + +本计划对应一次性交付版本,时间评估需要更现实。 + +### 建议总工期 + +- 15 到 20 个工作日 + +### 建议拆分 + +- 3 天:数据库、模型、Docmee 客户端 +- 3 天:工作流、自动配图、后端流式接口 +- 4 天:欢迎页、对话页、预览页基础 +- 3 天:继续修改、元素编辑、版本管理 +- 2 到 4 天:联调、测试、文档、修复 + +## 5. 关键风险与应对 + +### 风险 1:Docmee 渐进预览能力与 V2 主链路不完全一致 + +应对: + +- 优先按 V2 实现业务主链路 +- 必要时在后端内部做兼容适配 +- 前端不感知具体 Docmee 细节 + +### 风险 2:元素级编辑后导出链路边界不清晰 + +应对: + +- 本次先确保编辑快照可保存、可恢复、可继续修改参考 +- 下载默认保留最近生成结果下载能力 +- 在界面中清晰提示编辑态与下载稿关系 + +### 风险 3:版本对比功能范围失控 + +应对: + +- 本次版本对比以并排查看为主 +- 不做像素级 diff +- 重点保证“能切换、能看差异、能回退” + +## 6. Claude 实施提示 + +若将本计划交给 Claude / Codex / 其他 agentic 工具实施,必须遵守: + +- 优先复用现有项目代码模式 +- 不引入新的前端请求体系 +- 不用原生 `EventSource` +- 不新增 WebSocket 方案 +- 不让前端直连 Docmee +- 不把当前交付拆成一期 / 二期 +- 不因为实现难度而删除: + - 自动配图 + - 继续修改 PPT 成品 + - 元素级在线编辑 + - 版本对比 + +### 6.1 可直接发送给 Claude 的实施约束摘要 + +下面这段可以直接作为实现任务说明发送给 Claude。建议与规格文档、计划文档一起提供。 + +```text +请基于以下约束,直接在当前项目中实现 AI PPT 功能,不要重新发明一套新架构,也不要擅自缩 scope: + +1. 交付目标 +- 本次是单次交付版本,不拆一期 / 二期。 +- 目标是代码写完后,该功能在当前项目中可以直接跑通主链路。 +- 必须保留这些能力:自动配图、继续修改 PPT 成品、元素级在线编辑、版本管理与版本对比、完整会话恢复、预览、下载。 + +2. 前端技术约束 +- PPT 页面入口直接复用 `teacher-platform/src/views/LessonPrepPpt.vue`。 +- 不新增 tab,不改造 `LessonPrep.vue` 的页面导航结构。 +- 前端请求层复用 `teacher-platform/src/api/http.js` 的模式,不要新起一套 axios 或其他请求体系。 +- 流式方案必须复用教案页 `teacher-platform/src/views/LessonPlanPage.vue` 的 `fetch + reader` 模式。 +- 不使用原生 `EventSource`。 +- 不新增 WebSocket 替代 SSE,但仍然必须保留流式生成体验。 +- SSE 统一使用 `text/event-stream`,前端解析 `data: {...}` JSON,并根据 `type` 分发事件。 + +3. Docmee 接入约束 +- 前端不能直连 Docmee。 +- 前端不能持有 Docmee token。 +- 所有 Docmee 请求统一由后端代理。 +- 业务主链路优先按 Docmee V2 设计。 +- 如果渐进预览必须兼容旧接口,这个兼容逻辑只能放在后端,前端不感知 V1 / V2 差异。 + +4. PPT 预览与编辑约束 +- 预览必须优先复用 Docmee 官方渲染能力:`ppt2svg.js`、`ppt2canvas.js`。 +- 需要支持缩略图列表、大图预览、生成中进度更新、结果恢复。 +- 元素级编辑至少支持:文本编辑、位置移动、缩放、旋转。 +- 元素编辑保存为编辑快照,不要因为导出链路暂时复杂就删掉这个能力。 +- 预览阶段的“继续修改 PPT”与“元素级在线编辑”是两条并行能力,都要保留。 + +5. 后端实现约束 +- 数据库变更必须走 Alembic。 +- 新增 PPT 会话、大纲版本、消息记录、PPT 结果版本等核心模型。 +- LangGraph 需要保留,但只围绕业务主链路实现:知识检索、生成大纲、自动配图、审批中断、生成 PPT、继续修改再生成。 +- 不要为了“图编排很完整”而过度设计。 +- 服务层注意不要写错误的 `async with get_db() as db` 这种模式。 + +6. 版本能力约束 +- 大纲版本要保留。 +- PPT 结果版本要保留。 +- 版本对比必须可用,但采用务实方案: + - 支持用户选两个版本并排查看 + - 支持看大纲文本差异、模板差异、缩略图差异、生成时间、是否有编辑快照 + - 不要求做像素级 diff + +7. 明确不要做的事 +- 不要把功能拆成一期 / 二期再交付。 +- 不要删除自动配图。 +- 不要删除继续修改 PPT 成品。 +- 不要删除元素级在线编辑。 +- 不要删除版本对比。 +- 不要把 SSE 改成 WebSocket。 +- 不要让前端直接调用 `docmee.cn`。 +- 不要为了省事跳过 Alembic。 + +8. 实现优先级 +- 先打通后端数据模型、Docmee 代理、流式接口。 +- 再打通前端页面主状态、欢迎页、对话页、流式生成。 +- 再接入官方预览内核。 +- 再补继续修改、元素级编辑、版本管理与版本对比。 +- 最后做错误处理、恢复能力、测试和文档。 + +9. 完成标准 +- 用户可以新建 PPT 会话。 +- 用户可以选择知识库和模板。 +- 用户可以流式生成并审批大纲。 +- 用户可以看到自动配图结果。 +- 用户可以流式看到 PPT 生成进度。 +- 用户可以在预览页浏览缩略图和大图。 +- 用户可以继续通过聊天修改 PPT,并生成新版本。 +- 用户可以直接编辑预览中的文本 / 位置 / 缩放 / 旋转,并保存快照。 +- 用户可以查看并对比版本。 +- 用户刷新页面后可以恢复最近状态。 +- 用户可以下载结果。 + +如果实现过程中发现 Docmee 某个能力和预期不完全一致,不要直接删功能,优先通过后端兼容、降级展示、补充状态说明来保住整体链路。 +``` + +## 7. 完成定义 + +只有以下事项全部达成,才算计划完成: + +- 后端接口可用 +- 前端完整链路可跑通 +- 所有本次交付功能均已上线到当前项目 +- 核心测试通过 +- 文档补齐 diff --git a/docs/superpowers/specs/2326-3-18-ppt-generation-spec.md b/docs/superpowers/specs/2326-3-18-ppt-generation-spec.md new file mode 100644 index 0000000..1c43275 --- /dev/null +++ b/docs/superpowers/specs/2326-3-18-ppt-generation-spec.md @@ -0,0 +1,626 @@ +# AI PPT 生成功能规格说明(单次交付版) + +更新时间:2026-03-18 + +## 1. 文档目标 + +本文档定义当前项目中的 AI PPT 生成功能规格。本文档对应的是一次性交付版本,不做“一期 / 二期”拆分;实现顺序可以分阶段推进,但交付目标是功能整体可用。 + +本次交付在保留完整业务能力的前提下,统一技术路线,避免实现过程中出现以下问题: + +- 前端流式方案与现有项目模式不一致 +- Docmee 接入路线摇摆 +- 预览能力与业务接口脱节 +- 过度理想化的工作流设计阻塞主功能落地 + +## 2. 本次交付范围 + +### 2.1 必须实现 + +- 新建 PPT 会话、查看历史会话、恢复上次进度 +- 选择知识库并结合知识库生成 PPT 大纲 +- 选择模板并生成 PPT +- 大纲流式生成 +- 大纲编辑、审批、版本保留 +- 自动配图 +- PPT 生成进度流式更新 +- 使用官方 `ppt2svg` / `ppt2canvas` 进行缩略图与大图预览 +- 预览阶段继续通过聊天方式修改 PPT 成品 +- 预览阶段支持元素级在线编辑 + - 本次交付范围内至少支持文本编辑、位置移动、缩放、旋转 +- PPT 结果版本保留与版本对比 +- 下载生成结果 + +### 2.2 明确不做 + +- WebSocket 替代 SSE + +说明: + +- 本次交付仍然保留流式生成能力。 +- 流式传输继续使用 `text/event-stream + fetch + reader`,不额外引入 WebSocket。 + +## 3. 与现有项目对齐的核心决策 + +| 主题 | 决策 | +|------|------| +| 前端入口 | 复用现有 [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue) 作为页面入口,不新增新的课前准备 tab | +| 前端流式方案 | 复用教案页 [LessonPlanPage.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPlanPage.vue) 的 `fetch + reader` 模式,不使用原生 `EventSource` | +| 前端 API 基础设施 | 复用 [http.js](/d:/123/AIsystem/teacher-platform/src/api/http.js) 的 `resolveApiUrl` / `authFetch` / `apiRequest` 模式,不新建 axios 体系 | +| 后端接入方式 | 所有 Docmee 请求均由后端代理,前端不直连 Docmee | +| Docmee 主路线 | 业务主链路优先使用 Docmee V2;如渐进预览必须依赖旧接口,由后端在内部做兼容适配,前端不感知 V1 / V2 差异 | +| PPT 预览 | 复用 Docmee 官方前端项目中的 `ppt2svg.js` 与 `ppt2canvas.js`,并在当前项目内封装使用 | +| 数据库存储 | 使用 Alembic 管理迁移;不依赖 `create_all` 作为最终交付方案 | +| 状态管理 | 页面主状态以 PPT 页面根组件管理为主,可按需拆出 API/预览辅助模块;避免为了功能上线额外引入不必要的全局复杂度 | +| LangGraph 作用 | LangGraph 用于支撑知识检索、生成、审批中断、修改再生成等核心业务流程,但设计必须服务业务,不追求过度复杂的图结构 | +| 安全策略 | Markdown 渲染必须显式做转义或 sanitize,不能直接假设 `marked` 自动安全 | + +## 4. 用户流程 + +### 4.1 阶段 1:欢迎页 + +用户进入 PPT 页面后,默认进入欢迎页。 + +欢迎页包含: + +- 标题与引导说明 +- 常用预设卡片 +- 文本输入框 +- 模板入口 +- 知识库选择入口 +- 可选附件入口 + +用户可以通过三种方式进入生成流程: + +- 点击预设卡片 +- 直接输入需求 +- 先选择模板 / 知识库,再输入需求 + +### 4.2 阶段 2:对话与大纲页 + +用户输入需求后进入对话页。 + +对话页负责: + +- 展示用户消息与系统消息 +- 展示流式生成中的文字 +- 展示当前大纲卡片 +- 支持编辑大纲 +- 支持审批大纲 +- 在已有大纲基础上继续补充需求 + +当用户审批通过后,系统开始 PPT 生成。 + +### 4.3 阶段 3:预览页 + +PPT 进入生成或生成完成后进入预览页。 + +预览页负责: + +- 左侧显示聊天上下文与继续修改输入框 +- 左侧显示缩略图列表 +- 右侧显示大图预览 +- 显示生成进度 +- 支持切换版本 +- 支持元素级编辑 +- 支持保存编辑快照 +- 支持下载 + +### 4.4 继续修改 PPT 成品 + +继续修改是本次交付范围内必须支持的能力。 + +定义如下: + +- 用户在预览阶段输入自然语言修改要求 +- 系统基于“当前有效大纲 + 当前 PPT 结果 + 用户指令”重新生成新的大纲版本和 / 或新的 PPT 版本 +- 新版本生成后保留旧版本,用户可以做版本对比并切换 + +该能力是“内容层修改”的主链路。 + +### 4.5 元素级在线编辑 + +元素级在线编辑也是本次交付范围内必须支持的能力。 + +定义如下: + +- 基于官方 `ppt2svg` 的编辑能力在前端直接修改当前预览对象 +- 至少支持文本修改、移动、缩放、旋转 +- 编辑结果保存为当前 PPT 结果的“编辑态快照” +- 用户刷新页面后可以恢复编辑态 + +说明: + +- 元素编辑与“继续修改 PPT 成品”是两条并行能力 +- 内容级修改用于重新生成 +- 元素级编辑用于快速微调展示 + +## 5. 总体架构 + +### 5.1 后端架构 + +后端新增 `app/services/ppt/` 模块,职责如下: + +- Docmee API 封装 +- 大纲生成与审批工作流 +- 自动配图 +- 结果版本管理 +- 编辑快照持久化 +- SSE 流式输出 + +核心分层: + +- `models/`:PPT 会话、消息、大纲、结果 +- `schemas/`:PPT 相关请求与响应 +- `services/ppt/`:Docmee、工作流、图片搜索、编辑快照 +- `api/ppt.py`:对外 REST / SSE 接口 + +### 5.2 前端架构 + +前端沿用当前项目的“页面根组件负责业务编排,子组件负责显示”的模式。 + +入口页面: + +- [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue) + +页面根组件负责: + +- 当前阶段切换 +- 流式请求控制 +- 会话加载与恢复 +- 当前消息 / 大纲 / 模板 / 结果 / 版本状态 + +子组件负责: + +- 欢迎页 +- 聊天流 +- 大纲卡片 +- PPT 结果卡片 +- 预览面板 +- 缩略图列表 +- 工具栏 +- 版本对比弹窗 + +### 5.3 流式协议 + +本项目不使用原生 `EventSource`。 + +统一采用: + +- 后端返回 `text/event-stream` +- 前端使用 `fetch + reader` +- 每个 SSE 块统一只发送 `data: {...}\n\n` +- 前端通过 JSON 中的 `type` 字段区分事件类型 + +这样可以直接复用教案页的解析逻辑,减少协议复杂度。 + +## 6. Docmee 集成策略 + +### 6.1 主路线 + +业务主链路优先按 Docmee V2 设计,能力目标包括: + +- 创建任务 +- 生成内容 / 大纲 +- 更新内容 +- 生成 PPT +- 加载 PPT +- 下载 PPT +- 查询模板 + +### 6.2 兼容策略 + +若 Docmee 渐进预览能力在实际接入时需要依赖旧接口,例如: + +- 生成过程中轮询当前页数 +- 在生成进行中读取临时 `pptxProperty` + +则由后端封装为统一服务能力,前端仍只使用本项目自己的 `/api/v1/ppt/...` 接口。 + +### 6.3 前端不直接持有 Docmee token + +禁止前端直接: + +- 创建 Docmee API token +- 直接请求 `https://docmee.cn/api/...` +- 在浏览器保存 Docmee 凭证 + +所有 Docmee token 均由后端读取环境变量并代理请求。 + +## 7. 数据模型设计 + +### 7.1 `ppt_sessions` + +表示一次完整的 PPT 创作会话。 + +关键字段: + +- `id` +- `user_id` +- `title` +- `status` +- `current_outline_id` +- `current_result_id` +- `created_at` +- `updated_at` + +建议状态: + +- `draft` +- `generating_outline` +- `outline_ready` +- `generating_ppt` +- `preview_ready` +- `completed` +- `failed` + +### 7.2 `ppt_outlines` + +表示会话中的大纲版本。 + +关键字段: + +- `id` +- `session_id` +- `version` +- `content` +- `image_urls` +- `template_id` +- `knowledge_library_ids` +- `is_current` +- `created_at` + +说明: + +- 大纲审批、修改、继续生成都要保留版本 + +### 7.3 `ppt_messages` + +表示用户与系统在会话中的消息记录。 + +关键字段: + +- `id` +- `session_id` +- `role` +- `message_type` +- `content` +- `metadata` +- `created_at` + +建议 `message_type`: + +- `text` +- `outline` +- `ppt_result` +- `error` +- `system` + +### 7.4 `ppt_results` + +表示某个会话中的 PPT 结果版本。 + +关键字段: + +- `id` +- `session_id` +- `outline_id` +- `version` +- `is_current` +- `template_id` +- `docmee_ppt_id` +- `source_pptx_property` +- `edited_pptx_property` +- `file_url` +- `status` +- `current_page` +- `total_pages` +- `created_at` +- `completed_at` + +说明: + +- `source_pptx_property` 表示 Docmee 返回的原始预览数据 +- `edited_pptx_property` 表示前端元素编辑后保存的最新快照 +- 预览时优先使用 `edited_pptx_property`,没有则退回 `source_pptx_property` + +## 8. 后端接口设计 + +### 8.1 模板与会话 + +- `GET /api/v1/ppt/templates` + - 获取模板列表 + - 由后端代理 Docmee 模板接口 + +- `POST /api/v1/ppt/sessions` + - 创建会话 + +- `GET /api/v1/ppt/sessions` + - 获取当前用户的会话列表 + +- `GET /api/v1/ppt/sessions/{session_id}` + - 获取会话详情 + - 返回消息列表、当前大纲、当前 PPT 结果、结果版本列表 + +### 8.2 大纲生成与审批 + +- `POST /api/v1/ppt/stream/outline` + - 流式生成大纲 + - 输入:`session_id`、`user_input`、`knowledge_library_ids`、`template_id` + +- `POST /api/v1/ppt/outlines/{outline_id}/approve` + - 审批大纲 + - 可带修改后的大纲内容 + +### 8.3 PPT 生成与修改 + +- `POST /api/v1/ppt/stream/generate` + - 流式生成 PPT + - 输入:`session_id`、`outline_id`、`template_id` + +- `POST /api/v1/ppt/results/{result_id}/modify` + - 在当前 PPT 基础上继续修改 + - 输入:自然语言修改指令 + - 结果:创建新的大纲版本和 / 或新的 PPT 版本 + +### 8.4 编辑态保存与结果恢复 + +- `POST /api/v1/ppt/results/{result_id}/edit-snapshot` + - 保存编辑后的 `pptx_property` + +- `GET /api/v1/ppt/results/{result_id}` + - 获取指定 PPT 结果详情 + +- `POST /api/v1/ppt/results/{result_id}/download` + - 获取下载地址 + +### 8.5 版本对比 + +- `GET /api/v1/ppt/sessions/{session_id}/versions` + - 返回大纲版本与 PPT 结果版本摘要 + +版本对比本次交付采用务实设计: + +- 大纲版本对比:比较文本内容、更新时间、关联模板、关联结果 +- PPT 版本对比:比较版本元信息、缩略图、关联大纲、生成时间、编辑状态 + +不做像素级自动 diff,但必须支持用户在界面中选两个版本并进行并排查看。 + +## 9. SSE 事件协议 + +### 9.1 大纲流 + +后端统一输出 JSON 事件: + +```text +data: {"type":"meta","session_id":1} + +data: {"type":"assistant_chunk","content":"我将先整理需求..."} + +data: {"type":"outline_chunk","content":"# 标题\n"} + +data: {"type":"outline_ready","outline_id":12,"content":"...","image_urls":{}} + +data: {"type":"done"} +``` + +### 9.2 PPT 生成流 + +```text +data: {"type":"progress","current":1,"total":10,"result_id":8} + +data: {"type":"page_ready","page_index":0,"pptx_property":"..."} + +data: {"type":"result_ready","result_id":8,"ppt_id":"docmee_xxx","file_url":"..."} + +data: {"type":"done"} +``` + +### 9.3 错误事件 + +所有流式接口统一使用: + +```text +data: {"type":"error","message":"..."} +``` + +## 10. 前端组件设计 + +建议目录: + +```text +teacher-platform/src/components/ppt/ +├── PptWorkspace.vue +├── PptSidebar.vue +├── WelcomePanel.vue +├── TemplateSelector.vue +├── KnowledgeLibraryModal.vue +├── ChatPanel.vue +├── ChatMessage.vue +├── OutlineCard.vue +├── PptResultCard.vue +├── PptPreviewPanel.vue +├── PptThumbnailList.vue +├── PptCanvas.vue +├── PptToolbar.vue +├── PptVersionCompareDialog.vue +└── ChatInput.vue +``` + +说明: + +- 入口页仍为 [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue) +- 上述组件目录用于承载新 PPT 功能 + +## 11. 预览与编辑设计 + +### 11.1 预览 + +使用官方渲染工具: + +- `ppt2svg.js`:大图预览 +- `ppt2canvas.js`:缩略图 + +前端在读取结果时执行: + +1. 取 `edited_pptx_property` +2. 若为空,则取 `source_pptx_property` +3. 解压为对象 +4. 渲染缩略图与当前页 + +### 11.2 元素编辑 + +元素编辑基于官方 `ppt2svg` 的 edit 模式实现。 + +本次交付支持: + +- 文本修改 +- 位置拖拽 +- 缩放 +- 旋转 + +编辑行为触发时: + +1. 更新当前 `pptxObj` +2. 标记当前结果为“已编辑未保存” +3. 用户点击保存后调用 `edit-snapshot` 接口 +4. 后端保存最新 `edited_pptx_property` + +### 11.3 下载行为 + +下载默认下载当前有效 PPT 结果。 + +若存在已保存的编辑快照,则界面需要明确提示: + +- 当前下载对应最近一次生成结果 +- 编辑快照主要用于会话内预览恢复与继续修改参考 + +说明: + +- 若后续确认 Docmee 或本地转换链路支持“编辑快照导出为真实 PPTX”,可在实现中扩展 +- 但本次交付不能因为导出能力未完全闭环而放弃元素编辑 + +## 12. 自动配图设计 + +自动配图是本次交付必须实现能力。 + +设计如下: + +- 大纲生成后解析每一页标题 +- 通过 LLM 将页面标题翻译为英文图片搜索关键词 +- 调用 Unsplash 搜索横版图片 +- 将结果写入大纲版本的 `image_urls` +- 对话页的大纲卡片中展示图片预览 + +错误处理要求: + +- 自动配图失败不阻塞大纲审批 +- 无图时依然允许继续生成 PPT + +## 13. LangGraph 工作流设计 + +本次交付保留 LangGraph,但要求围绕业务主链路设计,不追求炫技式编排。 + +建议主流程: + +1. 用户输入需求 +2. 检索知识库 +3. 生成大纲 +4. 自动配图 +5. 大纲审批中断 +6. 审批通过后生成 PPT +7. 结果入库 +8. 继续修改时基于当前有效状态重新进入生成流程 + +要求: + +- 支持审批中断恢复 +- 支持继续修改触发新版本 +- 支持失败重试 +- 工作流节点数保持在“可测试、可维护”的范围内 + +## 14. 安全与约束 + +### 14.1 安全要求 + +- 所有 PPT 相关接口必须校验 JWT +- 会话 / 大纲 / 结果必须按 `user_id` 做鉴权 +- 前端不得保存 Docmee token +- Markdown 渲染必须转义或 sanitize + +### 14.2 工程约束 + +- 前端流式请求必须复用当前项目模式 +- 后端数据库变更必须走 Alembic +- 服务层不得直接使用错误的 `async with get_db() as db` 写法 +- 当前交付版本不引入 WebSocket + +## 15. 验收标准 + +以下全部满足,视为当前单次交付完成: + +- 用户能新建 PPT 会话 +- 用户能选择知识库与模板 +- 用户能输入需求并流式生成大纲 +- 用户能看到自动配图结果 +- 用户能编辑并审批大纲 +- 用户能流式看到 PPT 生成进度 +- 用户能在预览页浏览缩略图与大图 +- 用户能通过聊天继续修改 PPT +- 用户能直接编辑预览中的文本 / 位置 / 尺寸 / 旋转并保存 +- 用户能看到版本列表并做版本对比 +- 用户能刷新后恢复最近状态 +- 用户能下载结果 + +## 16. 实现风险 + +### 高风险 + +- Docmee V2 与渐进预览能力在真实项目中的匹配程度 +- 元素编辑后的导出链路能力边界 +- 版本对比 UI 的复杂度 + +### 中风险 + +- 自动配图的稳定性与速率限制 +- LangGraph 审批中断恢复 +- 预览渲染在大文件上的性能 + +### 低风险 + +- 欢迎页 / 聊天页 / 预览页的 UI 组装 +- 会话历史与版本列表展示 + +## 17. 成功原则 + +本功能的成功不是“架构最复杂”,而是: + +- 在当前项目中真实可用 +- 与现有代码风格一致 +- Claude 可以按文档直接实施 +- 用户从输入需求到下载 PPT 的完整链路可跑通 + +## 18. 实施备注 + +若将本规格直接交给 Claude / Codex / 其他 agentic 工具实施,默认还必须遵守以下约束: + +- 本次交付为单次交付版本,不拆一期 / 二期 +- 不得因为实现难度删除自动配图、继续修改 PPT 成品、元素级在线编辑、版本管理与版本对比 +- 只移除“WebSocket 替代 SSE”,但必须保留流式生成体验 +- 前端流式方案必须复用教案页的 `fetch + reader` 模式,不使用原生 `EventSource` +- PPT 页面入口复用 [LessonPrepPpt.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrepPpt.vue),不新增 tab,不调整 [LessonPrep.vue](/d:/123/AIsystem/teacher-platform/src/views/LessonPrep.vue) 导航结构 +- 前端请求层复用 [http.js](/d:/123/AIsystem/teacher-platform/src/api/http.js) 的模式,不新起一套 axios / 请求体系 +- 前端不能直连 Docmee,不能持有 Docmee token,所有 Docmee 请求统一由后端代理 +- Docmee 主链路优先按 V2 设计;如渐进预览需兼容旧接口,只能在后端做兼容,前端不感知 V1 / V2 差异 +- 预览必须优先复用官方 `ppt2svg.js` / `ppt2canvas.js` +- 元素级编辑至少支持文本编辑、位置移动、缩放、旋转,且编辑快照必须可保存、可恢复 +- 数据库变更必须走 Alembic +- LangGraph 需要保留,但只围绕业务主链路实现,不做过度复杂编排 + +实现优先级建议: + +1. 先打通后端数据模型、Docmee 代理、流式接口 +2. 再打通前端页面主状态、欢迎页、对话页、流式生成 +3. 再接入官方预览内核 +4. 再补继续修改、元素级编辑、版本管理与版本对比 +5. 最后补错误处理、恢复能力、测试和文档 From fec66390f68aa27399819bc2627648e0b0360980 Mon Sep 17 00:00:00 2001 From: zhezhitanye-code Date: Wed, 18 Mar 2026 12:24:03 +0800 Subject: [PATCH 2/8] feat(ppt): implement PPT generation full stack Backend: - Add PPT models (session, outline, message, result) with Alembic migration - Add Docmee API proxy client with token management and V2 task flow - Add auto image search service (Unsplash + LLM keyword translation) - Add LangGraph workflow (retrieve -> outline -> image -> approval) - Add PPT API routes: sessions, streaming outline, generate, modify, edit snapshot, download, versions Frontend: - Add ppt.js API client with SSE streaming support - Add components: WelcomePanel, ChatPanel, ChatMessage, ChatInput, OutlineCard, TemplateSelector, KnowledgeLibraryModal, PptSidebar, PptThumbnailList, PptCanvas - Rewrite LessonPrepPpt.vue with 3-stage flow (welcome -> chat -> preview) - Add schemas/ppt.py with all request/response models --- .claude/settings.local.json | 5 +- backend/.env.example | 11 + .../alembic/versions/add_ppt_tables_001.py | 115 ++ backend/app/api/__init__.py | 2 + backend/app/api/ppt.py | 651 +++++++ backend/app/core/config.py | 10 + backend/app/models/__init__.py | 8 + backend/app/models/ppt_message.py | 65 + backend/app/models/ppt_outline.py | 80 + backend/app/models/ppt_result.py | 109 ++ backend/app/models/ppt_session.py | 83 + backend/app/models/user.py | 5 + backend/app/schemas/ppt.py | 131 ++ backend/app/services/ppt/__init__.py | 1 + backend/app/services/ppt/docmee_client.py | 209 +++ backend/app/services/ppt/image_search.py | 108 ++ backend/app/services/ppt/nodes.py | 134 ++ backend/app/services/ppt/state.py | 42 + backend/app/services/ppt/workflow.py | 70 + ...c.md => 2026-03-18-ppt-generation-spec.md} | 0 teacher-platform/src/api/ppt.js | 120 ++ .../src/components/ppt/ChatInput.vue | 102 + .../src/components/ppt/ChatMessage.vue | 60 + .../src/components/ppt/ChatPanel.vue | 55 + .../components/ppt/KnowledgeLibraryModal.vue | 141 ++ .../src/components/ppt/OutlineCard.vue | 234 +++ .../src/components/ppt/PptCanvas.vue | 68 + .../src/components/ppt/PptSidebar.vue | 94 + .../src/components/ppt/PptThumbnailList.vue | 57 + .../src/components/ppt/TemplateSelector.vue | 131 ++ .../src/components/ppt/WelcomePanel.vue | 290 +++ teacher-platform/src/views/LessonPrepPpt.vue | 1655 ++++++----------- 32 files changed, 3712 insertions(+), 1134 deletions(-) create mode 100644 backend/alembic/versions/add_ppt_tables_001.py create mode 100644 backend/app/api/ppt.py create mode 100644 backend/app/models/ppt_message.py create mode 100644 backend/app/models/ppt_outline.py create mode 100644 backend/app/models/ppt_result.py create mode 100644 backend/app/models/ppt_session.py create mode 100644 backend/app/schemas/ppt.py create mode 100644 backend/app/services/ppt/__init__.py create mode 100644 backend/app/services/ppt/docmee_client.py create mode 100644 backend/app/services/ppt/image_search.py create mode 100644 backend/app/services/ppt/nodes.py create mode 100644 backend/app/services/ppt/state.py create mode 100644 backend/app/services/ppt/workflow.py rename docs/superpowers/specs/{2326-3-18-ppt-generation-spec.md => 2026-03-18-ppt-generation-spec.md} (100%) create mode 100644 teacher-platform/src/api/ppt.js create mode 100644 teacher-platform/src/components/ppt/ChatInput.vue create mode 100644 teacher-platform/src/components/ppt/ChatMessage.vue create mode 100644 teacher-platform/src/components/ppt/ChatPanel.vue create mode 100644 teacher-platform/src/components/ppt/KnowledgeLibraryModal.vue create mode 100644 teacher-platform/src/components/ppt/OutlineCard.vue create mode 100644 teacher-platform/src/components/ppt/PptCanvas.vue create mode 100644 teacher-platform/src/components/ppt/PptSidebar.vue create mode 100644 teacher-platform/src/components/ppt/PptThumbnailList.vue create mode 100644 teacher-platform/src/components/ppt/TemplateSelector.vue create mode 100644 teacher-platform/src/components/ppt/WelcomePanel.vue diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 1e5fc24..1027fb7 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -13,7 +13,10 @@ "Bash(git:*)", "Bash(wc -l /d/Develop/Project/AIsystem/teacher-platform/src/views/*.vue | sort -rn | head -20)", "WebSearch", - "Bash(start:*)" + "Bash(start:*)", + "WebFetch(domain:docmee.cn)", + "WebFetch(domain:open.docmee.cn)", + "WebFetch(domain:github.com)" ] } } diff --git a/backend/.env.example b/backend/.env.example index acaa366..858993b 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -41,6 +41,17 @@ ANTHROPIC_API_KEY=sk-ant-your-anthropic-key # 免费额度: 1000次/月 TAVILY_API_KEY=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 +# ========== Docmee PPT 生成 API ========== +# Docmee API(用于 AI PPT 生成) +# 申请地址: https://open.docmee.cn/ +# 免费额度: 根据套餐而定 +DOCMEE_API_KEY=your-docmee-api-key + +# ========== Unsplash 图片搜索 API ========== +# Unsplash API(用于 PPT 自动配图) +# 申请地址: https://unsplash.com/developers +# 免费额度: 50次/小时 +UNSPLASH_ACCESS_KEY=your-unsplash-access-key # 应用配置 APP_HOST=0.0.0.0 diff --git a/backend/alembic/versions/add_ppt_tables_001.py b/backend/alembic/versions/add_ppt_tables_001.py new file mode 100644 index 0000000..1a5143d --- /dev/null +++ b/backend/alembic/versions/add_ppt_tables_001.py @@ -0,0 +1,115 @@ +"""add ppt tables + +Revision ID: add_ppt_tables_001 +Revises: 1b6dd46c3766 +Create Date: 2026-03-18 10:00:00.000000 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision: str = 'add_ppt_tables_001' +down_revision: Union[str, None] = '1b6dd46c3766' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ppt_sessions + op.create_table( + 'ppt_sessions', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('user_id', sa.Integer(), nullable=False), + sa.Column('title', sa.String(length=255), nullable=False), + sa.Column('status', sa.String(length=50), nullable=False), + sa.Column('current_outline_id', sa.Integer(), nullable=True), + sa.Column('current_result_id', sa.Integer(), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id'), + ) + op.create_index('ix_ppt_sessions_user_id', 'ppt_sessions', ['user_id']) + + # ppt_outlines + op.create_table( + 'ppt_outlines', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('session_id', sa.Integer(), nullable=False), + sa.Column('version', sa.Integer(), nullable=False), + sa.Column('content', sa.Text(), nullable=False), + sa.Column('image_urls', postgresql.JSONB(), nullable=True), + sa.Column('template_id', sa.String(length=100), nullable=True), + sa.Column('knowledge_library_ids', postgresql.JSONB(), nullable=True), + sa.Column('is_current', sa.Boolean(), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint(['session_id'], ['ppt_sessions.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id'), + ) + op.create_index('ix_ppt_outlines_session_id', 'ppt_outlines', ['session_id']) + + # ppt_messages + op.create_table( + 'ppt_messages', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('session_id', sa.Integer(), nullable=False), + sa.Column('role', sa.String(length=20), nullable=False), + sa.Column('message_type', sa.String(length=20), nullable=False), + sa.Column('content', sa.Text(), nullable=False), + sa.Column('metadata', postgresql.JSONB(), nullable=True), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.ForeignKeyConstraint(['session_id'], ['ppt_sessions.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id'), + ) + op.create_index('ix_ppt_messages_session_id', 'ppt_messages', ['session_id']) + + # ppt_results + op.create_table( + 'ppt_results', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('session_id', sa.Integer(), nullable=False), + sa.Column('outline_id', sa.Integer(), nullable=False), + sa.Column('version', sa.Integer(), nullable=False), + sa.Column('is_current', sa.Boolean(), nullable=False), + sa.Column('template_id', sa.String(length=100), nullable=True), + sa.Column('docmee_ppt_id', sa.String(length=200), nullable=True), + sa.Column('source_pptx_property', sa.Text(), nullable=True), + sa.Column('edited_pptx_property', sa.Text(), nullable=True), + sa.Column('file_url', sa.String(length=500), nullable=True), + sa.Column('status', sa.String(length=50), nullable=False), + sa.Column('current_page', sa.Integer(), nullable=False), + sa.Column('total_pages', sa.Integer(), nullable=False), + sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), + sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True), + sa.ForeignKeyConstraint(['session_id'], ['ppt_sessions.id'], ondelete='CASCADE'), + sa.ForeignKeyConstraint(['outline_id'], ['ppt_outlines.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id'), + ) + op.create_index('ix_ppt_results_session_id', 'ppt_results', ['session_id']) + + # 添加ppt_sessions的外键(延迟创建,因为依赖ppt_outlines和ppt_results) + op.create_foreign_key( + 'fk_ppt_sessions_current_outline', + 'ppt_sessions', 'ppt_outlines', + ['current_outline_id'], ['id'], + ondelete='SET NULL' + ) + op.create_foreign_key( + 'fk_ppt_sessions_current_result', + 'ppt_sessions', 'ppt_results', + ['current_result_id'], ['id'], + ondelete='SET NULL' + ) + + +def downgrade() -> None: + op.drop_constraint('fk_ppt_sessions_current_result', 'ppt_sessions', type_='foreignkey') + op.drop_constraint('fk_ppt_sessions_current_outline', 'ppt_sessions', type_='foreignkey') + op.drop_table('ppt_results') + op.drop_table('ppt_messages') + op.drop_table('ppt_outlines') + op.drop_table('ppt_sessions') diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py index f623c84..7c5c7da 100644 --- a/backend/app/api/__init__.py +++ b/backend/app/api/__init__.py @@ -5,6 +5,7 @@ from app.api import auth, courseware, chat, knowledge, libraries, data_analysis from app.api import html_upload, html_chat, html_export from app.api import lesson_plan, question_generate +from app.api import ppt api_router = APIRouter() @@ -20,5 +21,6 @@ api_router.include_router(html_export.router, prefix="/html", tags=["html"]) api_router.include_router(lesson_plan.router) api_router.include_router(question_generate.router) +api_router.include_router(ppt.router) __all__ = ["api_router"] diff --git a/backend/app/api/ppt.py b/backend/app/api/ppt.py new file mode 100644 index 0000000..aeccc6d --- /dev/null +++ b/backend/app/api/ppt.py @@ -0,0 +1,651 @@ +""" +PPT API 路由 + +提供会话管理、流式大纲生成、PPT生成、编辑快照、版本管理等接口。 +所有接口校验JWT,按user_id鉴权。 +""" +import json +import logging +from datetime import datetime, timezone + +from fastapi import APIRouter, Depends, HTTPException +from fastapi.responses import StreamingResponse +from sqlalchemy import select, update +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload + +from app.core.auth import get_current_user +from app.core.database import get_db +from app.models.user import User +from app.models.ppt_session import PptSession +from app.models.ppt_outline import PptOutline +from app.models.ppt_message import PptMessage +from app.models.ppt_result import PptResult +from app.schemas.ppt import ( + PptSessionCreate, PptSessionBrief, PptSessionDetail, + PptOutlineBrief, PptResultBrief, PptResultDetail, + OutlineStreamRequest, OutlineApproveRequest, + PptGenerateRequest, PptModifyRequest, + EditSnapshotRequest, VersionSummary, PptTemplate, +) +from app.services.ppt.docmee_client import docmee_client +from app.services.ppt.nodes import ( + generate_outline_streaming, modify_outline_streaming, +) +from app.services.ppt.image_search import auto_assign_images +from app.services.ppt.state import PptAgentState + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/ppt", tags=["ppt"]) + + +# ========== 辅助函数 ========== + +def sse_event(data: dict) -> str: + return f"data: {json.dumps(data, ensure_ascii=False)}\n\n" + + +async def _get_session_or_404( + session_id: int, user_id: int, db: AsyncSession +) -> PptSession: + result = await db.execute( + select(PptSession).where( + PptSession.id == session_id, + PptSession.user_id == user_id, + ) + ) + session = result.scalar_one_or_none() + if not session: + raise HTTPException(status_code=404, detail="会话不存在") + return session + + +# ========== 模板 ========== + +@router.get("/templates") +async def get_templates( + page: int = 1, + size: int = 20, + user: User = Depends(get_current_user), +): + """获取Docmee模板列表""" + try: + data = await docmee_client.get_templates(page=page, size=size) + token = await docmee_client._ensure_token() + templates = [] + for t in data.get("data", []): + cover = t.get("coverUrl", "") + if cover and "?" not in cover: + cover = f"{cover}?token={token}" + templates.append(PptTemplate( + id=str(t.get("id", "")), + title=t.get("subject"), + cover_url=cover, + category=t.get("category"), + )) + return {"total": data.get("total", 0), "templates": templates} + except Exception as e: + logger.error(f"获取模板失败: {e}") + raise HTTPException(status_code=502, detail=f"获取模板失败: {e}") + + +# ========== 会话管理 ========== + +@router.post("/sessions", response_model=PptSessionBrief) +async def create_session( + body: PptSessionCreate, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + session = PptSession(user_id=user.id, title=body.title) + db.add(session) + await db.flush() + await db.refresh(session) + return session + + +@router.get("/sessions", response_model=list[PptSessionBrief]) +async def list_sessions( + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + result = await db.execute( + select(PptSession) + .where(PptSession.user_id == user.id) + .order_by(PptSession.updated_at.desc()) + ) + return result.scalars().all() + + +@router.get("/sessions/{session_id}") +async def get_session_detail( + session_id: int, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + result = await db.execute( + select(PptSession) + .options( + selectinload(PptSession.messages), + selectinload(PptSession.outlines), + selectinload(PptSession.results), + ) + .where(PptSession.id == session_id, PptSession.user_id == user.id) + ) + session = result.scalar_one_or_none() + if not session: + raise HTTPException(status_code=404, detail="会话不存在") + + results_brief = [] + for r in session.results: + results_brief.append(PptResultBrief( + id=r.id, version=r.version, is_current=r.is_current, + template_id=r.template_id, docmee_ppt_id=r.docmee_ppt_id, + file_url=r.file_url, status=r.status, + current_page=r.current_page, total_pages=r.total_pages, + has_edit_snapshot=bool(r.edited_pptx_property), + created_at=r.created_at, completed_at=r.completed_at, + )) + + return PptSessionDetail( + id=session.id, title=session.title, status=session.status, + current_outline_id=session.current_outline_id, + current_result_id=session.current_result_id, + messages=session.messages, + outlines=session.outlines, + results=results_brief, + created_at=session.created_at, updated_at=session.updated_at, + ) + + +# ========== 大纲生成与审批 ========== + +@router.post("/stream/outline") +async def stream_outline( + body: OutlineStreamRequest, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """流式生成大纲""" + session = await _get_session_or_404(body.session_id, user.id, db) + + # 保存用户消息 + user_msg = PptMessage( + session_id=session.id, role="user", + message_type="text", content=body.user_input, + ) + db.add(user_msg) + session.status = "generating_outline" + await db.flush() + + # 构建状态 + state: PptAgentState = { + "session_id": session.id, + "user_id": user.id, + "messages": [], + "user_input": body.user_input, + "selected_library_ids": body.knowledge_library_ids, + "retrieved_context": "", + "template_id": body.template_id, + "outline_markdown": "", + "outline_id": None, + "outline_approved": False, + "image_urls": {}, + "result_id": None, + "docmee_task_id": None, + "next_action": "generate_outline", + "error_message": "", + } + + # 如果有知识库,先检索 + if body.knowledge_library_ids: + from app.services.ppt.nodes import retrieve_knowledge + retrieval_result = await retrieve_knowledge(state) + state["retrieved_context"] = retrieval_result.get("retrieved_context", "") + + async def event_generator(): + try: + yield sse_event({"type": "meta", "session_id": session.id}) + + # 流式生成大纲 + full_outline = "" + async for chunk in generate_outline_streaming(state): + full_outline += chunk + yield sse_event({"type": "outline_chunk", "content": chunk}) + + # 自动配图(不阻塞) + image_urls = await auto_assign_images(full_outline) + + # 计算版本号 + version_result = await db.execute( + select(PptOutline) + .where(PptOutline.session_id == session.id) + .order_by(PptOutline.version.desc()) + ) + last_outline = version_result.scalars().first() + new_version = (last_outline.version + 1) if last_outline else 1 + + # 将旧大纲标记为非当前 + if last_outline: + await db.execute( + update(PptOutline) + .where(PptOutline.session_id == session.id) + .values(is_current=False) + ) + + # 保存大纲 + outline = PptOutline( + session_id=session.id, + version=new_version, + content=full_outline, + image_urls=image_urls, + template_id=body.template_id, + knowledge_library_ids=body.knowledge_library_ids, + is_current=True, + ) + db.add(outline) + await db.flush() + await db.refresh(outline) + + # 更新会话 + session.current_outline_id = outline.id + session.status = "outline_ready" + + # 保存助手消息 + ai_msg = PptMessage( + session_id=session.id, role="assistant", + message_type="outline", content=full_outline, + metadata_={"outline_id": outline.id}, + ) + db.add(ai_msg) + await db.flush() + + yield sse_event({ + "type": "outline_ready", + "outline_id": outline.id, + "content": full_outline, + "image_urls": image_urls, + }) + yield sse_event({"type": "done"}) + + except Exception as e: + logger.error(f"大纲生成失败: {e}") + session.status = "failed" + yield sse_event({"type": "error", "message": str(e)}) + + return StreamingResponse( + event_generator(), + media_type="text/event-stream", + headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}, + ) + + +@router.post("/outlines/{outline_id}/approve") +async def approve_outline( + outline_id: int, + body: OutlineApproveRequest, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """审批大纲,可带修改后的内容""" + result = await db.execute( + select(PptOutline) + .join(PptSession, PptOutline.session_id == PptSession.id) + .where(PptOutline.id == outline_id, PptSession.user_id == user.id) + ) + outline = result.scalar_one_or_none() + if not outline: + raise HTTPException(status_code=404, detail="大纲不存在") + + if body.content: + outline.content = body.content + if body.image_urls is not None: + outline.image_urls = body.image_urls + + session = await _get_session_or_404(outline.session_id, user.id, db) + session.status = "outline_ready" + session.current_outline_id = outline.id + await db.flush() + + return {"message": "大纲已审批", "outline_id": outline.id} + + +# ========== PPT生成 ========== + +@router.post("/stream/generate") +async def stream_generate_ppt( + body: PptGenerateRequest, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """流式生成PPT""" + session = await _get_session_or_404(body.session_id, user.id, db) + + # 获取大纲 + outline_result = await db.execute( + select(PptOutline).where(PptOutline.id == body.outline_id) + ) + outline = outline_result.scalar_one_or_none() + if not outline: + raise HTTPException(status_code=404, detail="大纲不存在") + + template_id = body.template_id or outline.template_id + if not template_id: + raise HTTPException(status_code=400, detail="请选择模板") + + session.status = "generating_ppt" + await db.flush() + + async def event_generator(): + try: + # 创建Docmee任务 + task_id = await docmee_client.create_task( + content=outline.content, task_type=7 + ) + + # 计算版本号 + ver_result = await db.execute( + select(PptResult) + .where(PptResult.session_id == session.id) + .order_by(PptResult.version.desc()) + ) + last_result = ver_result.scalars().first() + new_version = (last_result.version + 1) if last_result else 1 + + # 将旧结果标记为非当前 + if last_result: + await db.execute( + update(PptResult) + .where(PptResult.session_id == session.id) + .values(is_current=False) + ) + + # 创建结果记录 + ppt_result = PptResult( + session_id=session.id, + outline_id=outline.id, + version=new_version, + is_current=True, + template_id=template_id, + status="generating", + ) + db.add(ppt_result) + await db.flush() + await db.refresh(ppt_result) + + yield sse_event({ + "type": "progress", + "current": 0, "total": 0, + "result_id": ppt_result.id, + }) + + # 调用Docmee生成PPT + ppt_info = await docmee_client.generate_pptx( + task_id=task_id, + template_id=template_id, + markdown=outline.content, + ) + + ppt_id = ppt_info.get("id", "") + pptx_property = ppt_info.get("pptxProperty", "") + + # 更新结果 + ppt_result.docmee_ppt_id = ppt_id + ppt_result.source_pptx_property = pptx_property + ppt_result.status = "completed" + ppt_result.completed_at = datetime.now(timezone.utc) + + # 解压获取页数 + if pptx_property: + pptx_obj = docmee_client.decompress_pptx_property(pptx_property) + pages = pptx_obj.get("slides", []) + ppt_result.total_pages = len(pages) + ppt_result.current_page = len(pages) + + # 获取下载地址 + try: + file_url = await docmee_client.download_pptx(ppt_id) + ppt_result.file_url = file_url + except Exception: + pass + + session.current_result_id = ppt_result.id + session.status = "preview_ready" + + # 保存消息 + result_msg = PptMessage( + session_id=session.id, role="assistant", + message_type="ppt_result", + content=f"PPT已生成完成,共{ppt_result.total_pages}页", + metadata_={"result_id": ppt_result.id}, + ) + db.add(result_msg) + await db.flush() + + yield sse_event({ + "type": "result_ready", + "result_id": ppt_result.id, + "ppt_id": ppt_id, + "file_url": ppt_result.file_url or "", + "total_pages": ppt_result.total_pages, + "pptx_property": pptx_property, + }) + yield sse_event({"type": "done"}) + + except Exception as e: + logger.error(f"PPT生成失败: {e}") + session.status = "failed" + yield sse_event({"type": "error", "message": str(e)}) + + return StreamingResponse( + event_generator(), + media_type="text/event-stream", + headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}, + ) + + +# ========== 继续修改PPT ========== + +@router.post("/results/{result_id}/modify") +async def modify_ppt( + result_id: int, + body: PptModifyRequest, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """在当前PPT基础上继续修改,生成新版本""" + result = await db.execute( + select(PptResult) + .join(PptSession, PptResult.session_id == PptSession.id) + .where(PptResult.id == result_id, PptSession.user_id == user.id) + ) + ppt_result = result.scalar_one_or_none() + if not ppt_result: + raise HTTPException(status_code=404, detail="PPT结果不存在") + + session = await _get_session_or_404(ppt_result.session_id, user.id, db) + outline_result = await db.execute( + select(PptOutline).where(PptOutline.id == ppt_result.outline_id) + ) + current_outline = outline_result.scalar_one_or_none() + + user_msg = PptMessage( + session_id=session.id, role="user", + message_type="text", content=body.instruction, + ) + db.add(user_msg) + session.status = "generating_outline" + await db.flush() + + state: PptAgentState = { + "session_id": session.id, "user_id": user.id, "messages": [], + "user_input": body.instruction, "selected_library_ids": [], + "retrieved_context": "", + "template_id": current_outline.template_id if current_outline else None, + "outline_markdown": current_outline.content if current_outline else "", + "outline_id": current_outline.id if current_outline else None, + "outline_approved": False, "image_urls": {}, + "result_id": ppt_result.id, "docmee_task_id": None, + "next_action": "modify", "error_message": "", + } + + async def modify_event_generator(): + try: + yield sse_event({"type": "meta", "session_id": session.id}) + full_outline = "" + async for chunk in modify_outline_streaming(state): + full_outline += chunk + yield sse_event({"type": "outline_chunk", "content": chunk}) + + image_urls = await auto_assign_images(full_outline) + + ver_result = await db.execute( + select(PptOutline) + .where(PptOutline.session_id == session.id) + .order_by(PptOutline.version.desc()) + ) + last = ver_result.scalars().first() + new_ver = (last.version + 1) if last else 1 + + await db.execute( + update(PptOutline) + .where(PptOutline.session_id == session.id) + .values(is_current=False) + ) + new_outline = PptOutline( + session_id=session.id, version=new_ver, + content=full_outline, image_urls=image_urls, + template_id=current_outline.template_id if current_outline else None, + is_current=True, + ) + db.add(new_outline) + await db.flush() + await db.refresh(new_outline) + + session.current_outline_id = new_outline.id + session.status = "outline_ready" + await db.flush() + + yield sse_event({ + "type": "outline_ready", "outline_id": new_outline.id, + "content": full_outline, "image_urls": image_urls, + }) + yield sse_event({"type": "done"}) + except Exception as e: + logger.error(f"PPT修改失败: {e}") + yield sse_event({"type": "error", "message": str(e)}) + + return StreamingResponse( + modify_event_generator(), + media_type="text/event-stream", + headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}, + ) + + +# ========== 编辑快照与结果 ========== + +@router.post("/results/{result_id}/edit-snapshot") +async def save_edit_snapshot( + result_id: int, + body: EditSnapshotRequest, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """保存编辑后的pptx_property快照""" + result = await db.execute( + select(PptResult) + .join(PptSession, PptResult.session_id == PptSession.id) + .where(PptResult.id == result_id, PptSession.user_id == user.id) + ) + ppt_result = result.scalar_one_or_none() + if not ppt_result: + raise HTTPException(status_code=404, detail="PPT结果不存在") + ppt_result.edited_pptx_property = body.edited_pptx_property + await db.flush() + return {"message": "编辑快照已保存", "result_id": result_id} + + +@router.get("/results/{result_id}", response_model=PptResultDetail) +async def get_result_detail( + result_id: int, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """获取PPT结果详情""" + result = await db.execute( + select(PptResult) + .join(PptSession, PptResult.session_id == PptSession.id) + .where(PptResult.id == result_id, PptSession.user_id == user.id) + ) + ppt_result = result.scalar_one_or_none() + if not ppt_result: + raise HTTPException(status_code=404, detail="PPT结果不存在") + return PptResultDetail( + id=ppt_result.id, version=ppt_result.version, + is_current=ppt_result.is_current, template_id=ppt_result.template_id, + docmee_ppt_id=ppt_result.docmee_ppt_id, + file_url=ppt_result.file_url, status=ppt_result.status, + current_page=ppt_result.current_page, total_pages=ppt_result.total_pages, + has_edit_snapshot=bool(ppt_result.edited_pptx_property), + created_at=ppt_result.created_at, completed_at=ppt_result.completed_at, + source_pptx_property=ppt_result.source_pptx_property, + edited_pptx_property=ppt_result.edited_pptx_property, + outline_id=ppt_result.outline_id, + ) + + +@router.post("/results/{result_id}/download") +async def download_result( + result_id: int, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """获取PPT下载地址""" + result = await db.execute( + select(PptResult) + .join(PptSession, PptResult.session_id == PptSession.id) + .where(PptResult.id == result_id, PptSession.user_id == user.id) + ) + ppt_result = result.scalar_one_or_none() + if not ppt_result: + raise HTTPException(status_code=404, detail="PPT结果不存在") + if not ppt_result.docmee_ppt_id: + raise HTTPException(status_code=400, detail="PPT尚未生成完成") + try: + file_url = await docmee_client.download_pptx(ppt_result.docmee_ppt_id, refresh=True) + ppt_result.file_url = file_url + await db.flush() + return {"file_url": file_url} + except Exception as e: + raise HTTPException(status_code=502, detail=f"获取下载地址失败: {e}") + + +# ========== 版本管理 ========== + +@router.get("/sessions/{session_id}/versions", response_model=VersionSummary) +async def get_versions( + session_id: int, + user: User = Depends(get_current_user), + db: AsyncSession = Depends(get_db), +): + """获取会话的大纲版本和PPT结果版本""" + await _get_session_or_404(session_id, user.id, db) + outlines_result = await db.execute( + select(PptOutline).where(PptOutline.session_id == session_id).order_by(PptOutline.version) + ) + results_result = await db.execute( + select(PptResult).where(PptResult.session_id == session_id).order_by(PptResult.version) + ) + outline_briefs = [PptOutlineBrief.model_validate(o) for o in outlines_result.scalars().all()] + result_briefs = [] + for r in results_result.scalars().all(): + result_briefs.append(PptResultBrief( + id=r.id, version=r.version, is_current=r.is_current, + template_id=r.template_id, docmee_ppt_id=r.docmee_ppt_id, + file_url=r.file_url, status=r.status, + current_page=r.current_page, total_pages=r.total_pages, + has_edit_snapshot=bool(r.edited_pptx_property), + created_at=r.created_at, completed_at=r.completed_at, + )) + return VersionSummary(outline_versions=outline_briefs, result_versions=result_briefs) diff --git a/backend/app/core/config.py b/backend/app/core/config.py index fa797a0..a2c76f0 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -84,6 +84,16 @@ class Settings(BaseSettings): # 例如 Windows: C:/Windows/Fonts/msyh.ttc DATA_ANALYSIS_FONT_PATH: str = "" + # ========== Docmee PPT 生成 ========== + DOCMEE_API_KEY: str = "" + DOCMEE_BASE_URL: str = "https://docmee.cn" + + # ========== Unsplash 图片搜索 ========== + UNSPLASH_ACCESS_KEY: str = "" + + # ========== SiliconFlow AI 生图 ========== + SILICONFLOW_API_KEY: str = "" + class Config: env_file = ".env" env_file_encoding = "utf-8" diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index 483c755..2b488ed 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -9,6 +9,10 @@ from app.models.token_blacklist import TokenBlacklist from app.models.lesson_plan import LessonPlan from app.models.lesson_plan_reference import LessonPlanReference +from app.models.ppt_session import PptSession +from app.models.ppt_outline import PptOutline +from app.models.ppt_message import PptMessage +from app.models.ppt_result import PptResult from app.models.enums import ( CoursewareType, CoursewareStatus, @@ -26,6 +30,10 @@ "TokenBlacklist", "LessonPlan", "LessonPlanReference", + "PptSession", + "PptOutline", + "PptMessage", + "PptResult", "CoursewareType", "CoursewareStatus", "ChatRole", diff --git a/backend/app/models/ppt_message.py b/backend/app/models/ppt_message.py new file mode 100644 index 0000000..35b698c --- /dev/null +++ b/backend/app/models/ppt_message.py @@ -0,0 +1,65 @@ +""" +PPT消息模型 +""" +from datetime import datetime, timezone +from sqlalchemy import String, DateTime, ForeignKey, Integer, Text +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.orm import Mapped, mapped_column, relationship +from app.core.database import Base + + +class PptMessage(Base): + """ + PPT会话消息表 + + 记录用户与系统在PPT会话中的消息 + """ + __tablename__ = "ppt_messages" + + id: Mapped[int] = mapped_column( + Integer, + primary_key=True, + autoincrement=True + ) + session_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("ppt_sessions.id", ondelete="CASCADE"), + nullable=False, + index=True + ) + role: Mapped[str] = mapped_column( + String(20), + nullable=False, + comment="user / assistant / system" + ) + message_type: Mapped[str] = mapped_column( + String(20), + nullable=False, + default="text", + comment="text / outline / ppt_result / error / system" + ) + content: Mapped[str] = mapped_column( + Text, + nullable=False + ) + metadata_: Mapped[dict | None] = mapped_column( + "metadata", + JSONB, + nullable=True, + default=None, + comment="附加元数据" + ) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + default=lambda: datetime.now(timezone.utc), + nullable=False + ) + + # 关联关系 + session: Mapped["PptSession"] = relationship( + "PptSession", + back_populates="messages" + ) + + def __repr__(self): + return f"" diff --git a/backend/app/models/ppt_outline.py b/backend/app/models/ppt_outline.py new file mode 100644 index 0000000..a15c2d4 --- /dev/null +++ b/backend/app/models/ppt_outline.py @@ -0,0 +1,80 @@ +""" +PPT大纲模型 +""" +from datetime import datetime, timezone +from sqlalchemy import String, DateTime, ForeignKey, Integer, Text, Boolean +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.orm import Mapped, mapped_column, relationship +from app.core.database import Base + + +class PptOutline(Base): + """ + PPT大纲版本表 + + 存储会话中的大纲版本,支持版本管理和审批流程 + """ + __tablename__ = "ppt_outlines" + + id: Mapped[int] = mapped_column( + Integer, + primary_key=True, + autoincrement=True + ) + session_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("ppt_sessions.id", ondelete="CASCADE"), + nullable=False, + index=True + ) + version: Mapped[int] = mapped_column( + Integer, + nullable=False, + default=1 + ) + content: Mapped[str] = mapped_column( + Text, + nullable=False + ) + image_urls: Mapped[dict] = mapped_column( + JSONB, + nullable=True, + default=dict, + comment="自动配图结果,格式: {page_index: image_url}" + ) + template_id: Mapped[str | None] = mapped_column( + String(100), + nullable=True, + comment="Docmee模板ID" + ) + knowledge_library_ids: Mapped[list] = mapped_column( + JSONB, + nullable=True, + default=list, + comment="关联的知识库ID列表" + ) + is_current: Mapped[bool] = mapped_column( + Boolean, + nullable=False, + default=True + ) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + default=lambda: datetime.now(timezone.utc), + nullable=False + ) + + # 关联关系 + session: Mapped["PptSession"] = relationship( + "PptSession", + back_populates="outlines", + foreign_keys=[session_id] + ) + results: Mapped[list["PptResult"]] = relationship( + "PptResult", + back_populates="outline", + cascade="all, delete-orphan" + ) + + def __repr__(self): + return f"" diff --git a/backend/app/models/ppt_result.py b/backend/app/models/ppt_result.py new file mode 100644 index 0000000..a26793a --- /dev/null +++ b/backend/app/models/ppt_result.py @@ -0,0 +1,109 @@ +""" +PPT结果模型 +""" +from datetime import datetime, timezone +from sqlalchemy import String, DateTime, ForeignKey, Integer, Text, Boolean +from sqlalchemy.orm import Mapped, mapped_column, relationship +from app.core.database import Base + + +class PptResult(Base): + """ + PPT结果版本表 + + 存储PPT生成结果,支持版本管理和编辑快照 + """ + __tablename__ = "ppt_results" + + id: Mapped[int] = mapped_column( + Integer, + primary_key=True, + autoincrement=True + ) + session_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("ppt_sessions.id", ondelete="CASCADE"), + nullable=False, + index=True + ) + outline_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("ppt_outlines.id", ondelete="CASCADE"), + nullable=False + ) + version: Mapped[int] = mapped_column( + Integer, + nullable=False, + default=1 + ) + is_current: Mapped[bool] = mapped_column( + Boolean, + nullable=False, + default=True + ) + template_id: Mapped[str | None] = mapped_column( + String(100), + nullable=True, + comment="Docmee模板ID" + ) + docmee_ppt_id: Mapped[str | None] = mapped_column( + String(200), + nullable=True, + comment="Docmee返回的PPT ID" + ) + source_pptx_property: Mapped[str | None] = mapped_column( + Text, + nullable=True, + comment="Docmee返回的原始预览数据" + ) + edited_pptx_property: Mapped[str | None] = mapped_column( + Text, + nullable=True, + comment="前端元素编辑后保存的最新快照" + ) + file_url: Mapped[str | None] = mapped_column( + String(500), + nullable=True, + comment="PPT下载地址" + ) + status: Mapped[str] = mapped_column( + String(50), + nullable=False, + default="generating", + comment="generating / completed / failed" + ) + current_page: Mapped[int] = mapped_column( + Integer, + nullable=False, + default=0, + comment="当前已生成页数" + ) + total_pages: Mapped[int] = mapped_column( + Integer, + nullable=False, + default=0, + comment="总页数" + ) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + default=lambda: datetime.now(timezone.utc), + nullable=False + ) + completed_at: Mapped[datetime | None] = mapped_column( + DateTime(timezone=True), + nullable=True + ) + + # 关联关系 + session: Mapped["PptSession"] = relationship( + "PptSession", + back_populates="results", + foreign_keys=[session_id] + ) + outline: Mapped["PptOutline"] = relationship( + "PptOutline", + back_populates="results" + ) + + def __repr__(self): + return f"" diff --git a/backend/app/models/ppt_session.py b/backend/app/models/ppt_session.py new file mode 100644 index 0000000..7a869a1 --- /dev/null +++ b/backend/app/models/ppt_session.py @@ -0,0 +1,83 @@ +""" +PPT会话模型 +""" +from datetime import datetime, timezone +from sqlalchemy import String, DateTime, ForeignKey, Integer +from sqlalchemy.orm import Mapped, mapped_column, relationship +from app.core.database import Base + + +class PptSession(Base): + """ + PPT会话表 + + 表示一次完整的PPT创作会话,包含多个消息、大纲版本和PPT结果版本 + """ + __tablename__ = "ppt_sessions" + + id: Mapped[int] = mapped_column( + Integer, + primary_key=True, + autoincrement=True + ) + user_id: Mapped[int] = mapped_column( + Integer, + ForeignKey("users.id", ondelete="CASCADE"), + nullable=False, + index=True + ) + title: Mapped[str] = mapped_column( + String(255), + nullable=False, + default="新建PPT" + ) + status: Mapped[str] = mapped_column( + String(50), + nullable=False, + default="draft" + ) + current_outline_id: Mapped[int | None] = mapped_column( + Integer, + ForeignKey("ppt_outlines.id", ondelete="SET NULL"), + nullable=True + ) + current_result_id: Mapped[int | None] = mapped_column( + Integer, + ForeignKey("ppt_results.id", ondelete="SET NULL"), + nullable=True + ) + created_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + default=lambda: datetime.now(timezone.utc), + nullable=False + ) + updated_at: Mapped[datetime] = mapped_column( + DateTime(timezone=True), + default=lambda: datetime.now(timezone.utc), + onupdate=lambda: datetime.now(timezone.utc), + nullable=False + ) + + # 关联关系 + user: Mapped["User"] = relationship("User", back_populates="ppt_sessions") + messages: Mapped[list["PptMessage"]] = relationship( + "PptMessage", + back_populates="session", + cascade="all, delete-orphan", + order_by="PptMessage.created_at" + ) + outlines: Mapped[list["PptOutline"]] = relationship( + "PptOutline", + back_populates="session", + cascade="all, delete-orphan", + foreign_keys="PptOutline.session_id" + ) + results: Mapped[list["PptResult"]] = relationship( + "PptResult", + back_populates="session", + cascade="all, delete-orphan", + foreign_keys="PptResult.session_id" + ) + + def __repr__(self): + return f"" diff --git a/backend/app/models/user.py b/backend/app/models/user.py index 4606e84..e8e2b4b 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -58,6 +58,11 @@ class User(Base): back_populates="owner", cascade="all, delete-orphan" ) + ppt_sessions: Mapped[list["PptSession"]] = relationship( + "PptSession", + back_populates="user", + cascade="all, delete-orphan" + ) def __repr__(self): return f"" diff --git a/backend/app/schemas/ppt.py b/backend/app/schemas/ppt.py new file mode 100644 index 0000000..6063088 --- /dev/null +++ b/backend/app/schemas/ppt.py @@ -0,0 +1,131 @@ +""" +PPT相关请求/响应Schema +""" +from datetime import datetime +from pydantic import BaseModel, Field + + +# ========== 会话 ========== + +class PptSessionCreate(BaseModel): + title: str = Field(default="新建PPT", max_length=255) + + +class PptSessionBrief(BaseModel): + id: int + title: str + status: str + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} + + +class PptOutlineBrief(BaseModel): + id: int + version: int + content: str + image_urls: dict | None = None + template_id: str | None = None + knowledge_library_ids: list | None = None + is_current: bool + created_at: datetime + + model_config = {"from_attributes": True} + + +class PptMessageBrief(BaseModel): + id: int + role: str + message_type: str + content: str + metadata_: dict | None = Field(None, alias="metadata_") + created_at: datetime + + model_config = {"from_attributes": True, "populate_by_name": True} + + +class PptResultBrief(BaseModel): + id: int + version: int + is_current: bool + template_id: str | None = None + docmee_ppt_id: str | None = None + file_url: str | None = None + status: str + current_page: int + total_pages: int + has_edit_snapshot: bool = False + created_at: datetime + completed_at: datetime | None = None + + model_config = {"from_attributes": True} + + +class PptResultDetail(PptResultBrief): + source_pptx_property: str | None = None + edited_pptx_property: str | None = None + outline_id: int + + +class PptSessionDetail(BaseModel): + id: int + title: str + status: str + current_outline_id: int | None = None + current_result_id: int | None = None + messages: list[PptMessageBrief] = [] + outlines: list[PptOutlineBrief] = [] + results: list[PptResultBrief] = [] + created_at: datetime + updated_at: datetime + + model_config = {"from_attributes": True} + + +# ========== 大纲 ========== + +class OutlineStreamRequest(BaseModel): + session_id: int + user_input: str = Field(..., min_length=1) + knowledge_library_ids: list[int] = Field(default_factory=list) + template_id: str | None = None + + +class OutlineApproveRequest(BaseModel): + content: str | None = None + image_urls: dict | None = None + + +# ========== PPT生成 ========== + +class PptGenerateRequest(BaseModel): + session_id: int + outline_id: int + template_id: str | None = None + + +class PptModifyRequest(BaseModel): + instruction: str = Field(..., min_length=1) + + +# ========== 编辑快照 ========== + +class EditSnapshotRequest(BaseModel): + edited_pptx_property: str + + +# ========== 版本 ========== + +class VersionSummary(BaseModel): + outline_versions: list[PptOutlineBrief] = [] + result_versions: list[PptResultBrief] = [] + + +# ========== 模板 ========== + +class PptTemplate(BaseModel): + id: str + title: str | None = None + cover_url: str | None = None + category: str | None = None diff --git a/backend/app/services/ppt/__init__.py b/backend/app/services/ppt/__init__.py new file mode 100644 index 0000000..5d92ffb --- /dev/null +++ b/backend/app/services/ppt/__init__.py @@ -0,0 +1 @@ +"""PPT生成服务模块""" diff --git a/backend/app/services/ppt/docmee_client.py b/backend/app/services/ppt/docmee_client.py new file mode 100644 index 0000000..7d239d9 --- /dev/null +++ b/backend/app/services/ppt/docmee_client.py @@ -0,0 +1,209 @@ +""" +Docmee API 代理客户端 + +所有Docmee请求均由后端代理,前端不直连Docmee。 +业务主链路优先使用V2接口。 +""" +import base64 +import gzip +import json +import logging +from typing import AsyncIterator + +import httpx + +from app.core.config import settings + +logger = logging.getLogger(__name__) + +DOCMEE_OPEN_URL = "https://open.docmee.cn" + + +class DocmeeClient: + """Docmee API封装""" + + def __init__(self): + self._token: str | None = None + + async def _ensure_token(self) -> str: + """获取或刷新API Token""" + if self._token: + return self._token + self._token = await self.create_api_token() + return self._token + + async def create_api_token(self, uid: str = "system") -> str: + """创建API Token""" + async with httpx.AsyncClient(timeout=30) as client: + resp = await client.post( + f"{DOCMEE_OPEN_URL}/api/user/createApiToken", + headers={ + "Content-Type": "application/json", + "Api-Key": settings.DOCMEE_API_KEY, + }, + json={"uid": uid, "timeOfHours": 2}, + ) + data = resp.json() + if data.get("code") != 0: + raise RuntimeError(f"Docmee createApiToken failed: {data.get('message')}") + return data["data"]["token"] + + async def _request(self, method: str, path: str, **kwargs) -> dict: + """通用请求封装,自动附加token""" + token = await self._ensure_token() + headers = kwargs.pop("headers", {}) + headers["token"] = token + + async with httpx.AsyncClient(timeout=60) as client: + resp = await client.request(method, f"{DOCMEE_OPEN_URL}{path}", headers=headers, **kwargs) + data = resp.json() + if data.get("code") != 0: + # token过期时重试一次 + if "token" in str(data.get("message", "")).lower(): + self._token = None + token = await self._ensure_token() + headers["token"] = token + resp = await client.request(method, f"{DOCMEE_OPEN_URL}{path}", headers=headers, **kwargs) + data = resp.json() + if data.get("code") != 0: + raise RuntimeError(f"Docmee API error: {data.get('message')}") + else: + raise RuntimeError(f"Docmee API error: {data.get('message')}") + return data + + # ========== 模板 ========== + + async def get_templates(self, page: int = 1, size: int = 20, category: str | None = None) -> dict: + """获取模板列表""" + filters = {"type": 1} + if category: + filters["category"] = category + return await self._request( + "POST", "/api/ppt/templates", + json={"page": page, "size": size, "filters": filters}, + ) + + # ========== V2 任务流程 ========== + + async def create_task(self, content: str, task_type: int = 1) -> str: + """创建PPT任务,返回任务ID + type: 1=智能生成, 7=Markdown大纲 + """ + token = await self._ensure_token() + async with httpx.AsyncClient(timeout=30) as client: + resp = await client.post( + f"{DOCMEE_OPEN_URL}/api/ppt/v2/createTask", + headers={"token": token}, + data={"type": str(task_type), "content": content}, + ) + data = resp.json() + if data.get("code") != 0: + raise RuntimeError(f"Docmee createTask failed: {data.get('message')}") + return data["data"]["id"] + + async def generate_content_stream(self, task_id: str, **kwargs) -> AsyncIterator[dict]: + """流式生成大纲内容""" + token = await self._ensure_token() + body = {"id": task_id, "stream": True, **kwargs} + async with httpx.AsyncClient(timeout=120) as client: + async with client.stream( + "POST", + f"{DOCMEE_OPEN_URL}/api/ppt/v2/generateContent", + headers={"Content-Type": "application/json", "token": token}, + json=body, + ) as resp: + async for line in resp.aiter_lines(): + line = line.strip() + if not line or line.startswith(":"): + continue + if line.startswith("data:"): + line = line[5:].strip() + try: + yield json.loads(line) + except json.JSONDecodeError: + continue + + async def generate_content(self, task_id: str, **kwargs) -> dict: + """非流式生成大纲内容""" + body = {"id": task_id, "stream": False, **kwargs} + return await self._request("POST", "/api/ppt/v2/generateContent", json=body) + + async def update_content_stream(self, task_id: str, markdown: str, question: str = "") -> AsyncIterator[dict]: + """流式更新大纲内容""" + token = await self._ensure_token() + body = {"id": task_id, "markdown": markdown, "stream": True} + if question: + body["question"] = question + async with httpx.AsyncClient(timeout=120) as client: + async with client.stream( + "POST", + f"{DOCMEE_OPEN_URL}/api/ppt/v2/updateContent", + headers={"Content-Type": "application/json", "token": token}, + json=body, + ) as resp: + async for line in resp.aiter_lines(): + line = line.strip() + if not line or line.startswith(":"): + continue + if line.startswith("data:"): + line = line[5:].strip() + try: + yield json.loads(line) + except json.JSONDecodeError: + continue + + async def generate_pptx(self, task_id: str, template_id: str, markdown: str) -> dict: + """生成PPT,返回pptInfo""" + data = await self._request( + "POST", "/api/ppt/v2/generatePptx", + json={"id": task_id, "templateId": template_id, "markdown": markdown}, + ) + return data.get("data", {}).get("pptInfo", {}) + + async def load_pptx(self, ppt_id: str) -> dict: + """加载PPT结果""" + data = await self._request("GET", f"/api/ppt/loadPptx?id={ppt_id}") + return data.get("data", {}).get("pptInfo", {}) + + async def download_pptx(self, ppt_id: str, refresh: bool = False) -> str: + """获取PPT下载地址""" + data = await self._request( + "POST", "/api/ppt/downloadPptx", + json={"id": ppt_id, "refresh": refresh}, + ) + return data.get("data", {}).get("fileUrl", "") + + async def save_pptx(self, ppt_id: str, pptx_property: dict | None = None) -> dict: + """保存PPT编辑""" + body = {"id": ppt_id, "drawPptx": True, "drawCover": True} + if pptx_property: + body["pptxProperty"] = pptx_property + return await self._request("POST", "/api/ppt/savePptx", json=body) + + # ========== 工具方法 ========== + + @staticmethod + def decompress_pptx_property(encoded: str) -> dict: + """解压pptxProperty: base64 -> gzip -> json""" + try: + compressed = base64.b64decode(encoded) + decompressed = gzip.decompress(compressed) + return json.loads(decompressed) + except Exception as e: + logger.error(f"Failed to decompress pptxProperty: {e}") + return {} + + @staticmethod + def compress_pptx_property(obj: dict) -> str: + """压缩pptxProperty: json -> gzip -> base64""" + try: + json_bytes = json.dumps(obj, ensure_ascii=False).encode("utf-8") + compressed = gzip.compress(json_bytes) + return base64.b64encode(compressed).decode("ascii") + except Exception as e: + logger.error(f"Failed to compress pptxProperty: {e}") + return "" + + +# 全局单例 +docmee_client = DocmeeClient() diff --git a/backend/app/services/ppt/image_search.py b/backend/app/services/ppt/image_search.py new file mode 100644 index 0000000..633a3e0 --- /dev/null +++ b/backend/app/services/ppt/image_search.py @@ -0,0 +1,108 @@ +""" +自动配图服务 + +从大纲中提取页面标题,通过LLM翻译为英文关键词,调用Unsplash搜索横版图片。 +配图失败不阻塞后续流程。 +""" +import logging +import re + +import httpx +from openai import AsyncOpenAI + +from app.core.config import settings + +logger = logging.getLogger(__name__) + +UNSPLASH_API = "https://api.unsplash.com" + + +def extract_page_titles(markdown: str) -> list[str]: + """从Markdown大纲中提取页面标题(一级和二级标题)""" + titles = [] + for line in markdown.split("\n"): + line = line.strip() + match = re.match(r"^#{1,2}\s+(.+)", line) + if match: + title = match.group(1).strip() + if title: + titles.append(title) + return titles + + +async def translate_to_search_keywords(titles: list[str]) -> list[str]: + """使用LLM将中文标题翻译为英文图片搜索关键词""" + if not titles: + return [] + try: + client = AsyncOpenAI( + api_key=settings.DASHSCOPE_API_KEY, + base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", + ) + prompt = ( + "将以下PPT页面标题翻译为简短的英文图片搜索关键词(每个标题一行,只输出关键词):\n" + + "\n".join(f"- {t}" for t in titles) + ) + resp = await client.chat.completions.create( + model=settings.LLM_MODEL, + messages=[{"role": "user", "content": prompt}], + temperature=0.3, + max_tokens=500, + ) + text = resp.choices[0].message.content.strip() + keywords = [line.strip().lstrip("- ").strip() for line in text.split("\n") if line.strip()] + return keywords + except Exception as e: + logger.warning(f"Failed to translate titles to keywords: {e}") + return titles + + +async def search_unsplash(keyword: str) -> str | None: + """搜索Unsplash横版图片,返回图片URL""" + if not settings.UNSPLASH_ACCESS_KEY: + return None + try: + async with httpx.AsyncClient(timeout=15) as client: + resp = await client.get( + f"{UNSPLASH_API}/search/photos", + params={ + "query": keyword, + "orientation": "landscape", + "per_page": 1, + }, + headers={"Authorization": f"Client-ID {settings.UNSPLASH_ACCESS_KEY}"}, + ) + data = resp.json() + results = data.get("results", []) + if results: + return results[0].get("urls", {}).get("regular", "") + except Exception as e: + logger.warning(f"Unsplash search failed for '{keyword}': {e}") + return None + + +async def auto_assign_images(markdown: str) -> dict: + """ + 自动配图主入口 + + 返回: {page_index: image_url} 映射 + 配图失败返回空字典,不抛异常 + """ + try: + titles = extract_page_titles(markdown) + if not titles: + return {} + + keywords = await translate_to_search_keywords(titles) + image_urls = {} + + for i, kw in enumerate(keywords): + url = await search_unsplash(kw) + if url: + image_urls[str(i)] = url + + logger.info(f"Auto image assignment: {len(image_urls)}/{len(titles)} pages got images") + return image_urls + except Exception as e: + logger.error(f"Auto image assignment failed: {e}") + return {} diff --git a/backend/app/services/ppt/nodes.py b/backend/app/services/ppt/nodes.py new file mode 100644 index 0000000..e92b28f --- /dev/null +++ b/backend/app/services/ppt/nodes.py @@ -0,0 +1,134 @@ +""" +PPT LangGraph 节点实现 + +围绕业务主链路:知识检索 -> 大纲生成 -> 自动配图 -> 审批中断 -> PPT生成 +""" +import logging +from typing import AsyncIterator + +from langchain_core.messages import AIMessage, HumanMessage +from openai import AsyncOpenAI + +from app.core.config import settings +from app.services.ppt.state import PptAgentState +from app.services.ppt.image_search import auto_assign_images + +logger = logging.getLogger(__name__) + + +def _get_llm_client() -> AsyncOpenAI: + return AsyncOpenAI( + api_key=settings.DASHSCOPE_API_KEY, + base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", + ) + + +async def retrieve_knowledge(state: PptAgentState) -> dict: + """检索知识库获取相关上下文""" + library_ids = state.get("selected_library_ids", []) + user_input = state.get("user_input", "") + + if not library_ids or not user_input: + return {"retrieved_context": ""} + + try: + from app.services.rag.hybrid_retriever import HybridRetriever + retriever = HybridRetriever(user_id=state["user_id"]) + docs = await retriever.retrieve(user_input, library_ids=library_ids, top_k=5) + context = "\n\n".join(doc.page_content for doc in docs) + return {"retrieved_context": context} + except Exception as e: + logger.warning(f"Knowledge retrieval failed: {e}") + return {"retrieved_context": ""} + + +async def generate_outline_streaming(state: PptAgentState) -> AsyncIterator[str]: + """流式生成大纲,yield每个文本块""" + user_input = state.get("user_input", "") + context = state.get("retrieved_context", "") + template_id = state.get("template_id") + + system_prompt = """你是一个专业的PPT大纲生成助手。根据用户需求生成结构化的PPT大纲。 + +要求: +1. 使用Markdown格式 +2. 一级标题(#)为PPT主题 +3. 二级标题(##)为每页标题 +4. 每页下用要点列表描述内容 +5. 页数控制在8-15页 +6. 内容专业、结构清晰""" + + if context: + system_prompt += f"\n\n参考知识库内容:\n{context}" + + if template_id: + system_prompt += f"\n\n使用模板ID: {template_id}" + + client = _get_llm_client() + stream = await client.chat.completions.create( + model=settings.LLM_MODEL, + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": f"请为以下主题生成PPT大纲:\n{user_input}"}, + ], + temperature=0.7, + stream=True, + ) + + async for chunk in stream: + delta = chunk.choices[0].delta + if delta.content: + yield delta.content + + +async def generate_outline(state: PptAgentState) -> dict: + """非流式生成大纲(用于LangGraph节点)""" + full_text = "" + async for chunk in generate_outline_streaming(state): + full_text += chunk + + return { + "outline_markdown": full_text, + "messages": [AIMessage(content=full_text)], + "next_action": "auto_image", + } + + +async def auto_image_node(state: PptAgentState) -> dict: + """自动配图节点""" + markdown = state.get("outline_markdown", "") + image_urls = await auto_assign_images(markdown) + return { + "image_urls": image_urls, + "next_action": "approve", + } + + +async def approval_node(state: PptAgentState) -> dict: + """审批中断节点 - 等待用户确认大纲""" + return { + "outline_approved": False, + "next_action": "waiting_approval", + } + + +async def modify_outline_streaming(state: PptAgentState) -> AsyncIterator[str]: + """流式修改大纲""" + user_input = state.get("user_input", "") + current_outline = state.get("outline_markdown", "") + + client = _get_llm_client() + stream = await client.chat.completions.create( + model=settings.LLM_MODEL, + messages=[ + {"role": "system", "content": "你是PPT大纲修改助手。根据用户的修改意见,在现有大纲基础上进行调整。保持Markdown格式。"}, + {"role": "user", "content": f"当前大纲:\n{current_outline}\n\n修改要求:\n{user_input}"}, + ], + temperature=0.7, + stream=True, + ) + + async for chunk in stream: + delta = chunk.choices[0].delta + if delta.content: + yield delta.content diff --git a/backend/app/services/ppt/state.py b/backend/app/services/ppt/state.py new file mode 100644 index 0000000..6d22f26 --- /dev/null +++ b/backend/app/services/ppt/state.py @@ -0,0 +1,42 @@ +""" +PPT LangGraph 状态定义 +""" +from typing import TypedDict, Annotated +from langgraph.graph.message import add_messages +from langchain_core.messages import BaseMessage + + +class PptAgentState(TypedDict): + """PPT工作流状态""" + # 会话信息 + session_id: int + user_id: int + + # 消息历史 + messages: Annotated[list[BaseMessage], add_messages] + + # 用户输入 + user_input: str + + # 知识库 + selected_library_ids: list[int] + retrieved_context: str + + # 模板 + template_id: str | None + + # 大纲 + outline_markdown: str + outline_id: int | None + outline_approved: bool + + # 配图 + image_urls: dict + + # PPT结果 + result_id: int | None + docmee_task_id: str | None + + # 流程控制 + next_action: str # generate_outline / approve / generate_ppt / modify / done / error + error_message: str diff --git a/backend/app/services/ppt/workflow.py b/backend/app/services/ppt/workflow.py new file mode 100644 index 0000000..8ad184c --- /dev/null +++ b/backend/app/services/ppt/workflow.py @@ -0,0 +1,70 @@ +""" +PPT LangGraph 工作流 + +业务主链路:知识检索 -> 大纲生成 -> 自动配图 -> 审批中断 -> PPT生成 +支持审批中断恢复和继续修改触发新版本。 +""" +import logging + +from langgraph.graph import StateGraph, END +from langgraph.checkpoint.memory import MemorySaver + +from app.services.ppt.state import PptAgentState +from app.services.ppt.nodes import ( + retrieve_knowledge, + generate_outline, + auto_image_node, + approval_node, +) + +logger = logging.getLogger(__name__) + + +def _route_after_approval(state: PptAgentState) -> str: + """审批后路由:已批准则结束,否则等待""" + if state.get("outline_approved"): + return "end" + return "wait" + + +def create_ppt_graph(): + """ + 创建PPT工作流图 + + 流程: + 1. retrieve - 检索知识库 + 2. outline - 生成大纲 + 3. image - 自动配图 + 4. approval - 审批中断(等待用户确认) + """ + workflow = StateGraph(PptAgentState) + + workflow.add_node("retrieve", retrieve_knowledge) + workflow.add_node("outline", generate_outline) + workflow.add_node("image", auto_image_node) + workflow.add_node("approval", approval_node) + + workflow.set_entry_point("retrieve") + workflow.add_edge("retrieve", "outline") + workflow.add_edge("outline", "image") + workflow.add_edge("image", "approval") + workflow.add_edge("approval", END) + + memory = MemorySaver() + return workflow.compile( + checkpointer=memory, + interrupt_after=["approval"], + ) + + +# 全局单例 +_ppt_graph = None + + +def get_ppt_graph(): + """获取PPT工作流图实例""" + global _ppt_graph + if _ppt_graph is None: + _ppt_graph = create_ppt_graph() + logger.info("PPT工作流图初始化完成") + return _ppt_graph diff --git a/docs/superpowers/specs/2326-3-18-ppt-generation-spec.md b/docs/superpowers/specs/2026-03-18-ppt-generation-spec.md similarity index 100% rename from docs/superpowers/specs/2326-3-18-ppt-generation-spec.md rename to docs/superpowers/specs/2026-03-18-ppt-generation-spec.md diff --git a/teacher-platform/src/api/ppt.js b/teacher-platform/src/api/ppt.js new file mode 100644 index 0000000..fb9720d --- /dev/null +++ b/teacher-platform/src/api/ppt.js @@ -0,0 +1,120 @@ +/** + * PPT API 封装 + * + * 复用 http.js 的 resolveApiUrl / authFetch / apiRequest 模式 + */ +import { resolveApiUrl, getToken, apiRequest, authFetch } from './http.js' + +// ========== 模板 ========== + +export function getTemplates(page = 1, size = 20) { + return apiRequest(`/api/v1/ppt/templates?page=${page}&size=${size}`) +} + +// ========== 会话 ========== + +export function createSession(title = '新建PPT') { + return apiRequest('/api/v1/ppt/sessions', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ title }), + }) +} + +export function listSessions() { + return apiRequest('/api/v1/ppt/sessions') +} + +export function getSessionDetail(sessionId) { + return apiRequest(`/api/v1/ppt/sessions/${sessionId}`) +} + +// ========== 大纲 ========== + +export function approveOutline(outlineId, content = null, imageUrls = null) { + const body = {} + if (content !== null) body.content = content + if (imageUrls !== null) body.image_urls = imageUrls + return apiRequest(`/api/v1/ppt/outlines/${outlineId}/approve`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }) +} + +// ========== PPT结果 ========== + +export function getResultDetail(resultId) { + return apiRequest(`/api/v1/ppt/results/${resultId}`) +} + +export function saveEditSnapshot(resultId, editedPptxProperty) { + return apiRequest(`/api/v1/ppt/results/${resultId}/edit-snapshot`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ edited_pptx_property: editedPptxProperty }), + }) +} + +export function downloadResult(resultId) { + return apiRequest(`/api/v1/ppt/results/${resultId}/download`, { method: 'POST' }) +} + +// ========== 版本 ========== + +export function getVersions(sessionId) { + return apiRequest(`/api/v1/ppt/sessions/${sessionId}/versions`) +} + +// ========== 流式请求 (fetch + reader) ========== + +/** + * 通用SSE流式请求 + * 复用教案页的 fetch + reader 模式 + */ +export async function streamPptSSE(url, body, callbacks, abortSignal) { + const { onMeta, onChunk, onOutlineReady, onProgress, onPageReady, onResultReady, onDone, onError } = callbacks + + const res = await fetch(resolveApiUrl(url), { + method: 'POST', + headers: { + Authorization: `Bearer ${getToken()}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + signal: abortSignal, + }) + + if (!res.ok) throw new Error(`HTTP ${res.status}`) + + const reader = res.body.getReader() + const decoder = new TextDecoder() + let buffer = '' + + while (true) { + const { done, value } = await reader.read() + if (done) break + buffer += decoder.decode(value, { stream: true }) + const lines = buffer.split('\n\n') + buffer = lines.pop() || '' + + for (const line of lines) { + const trimmed = line.replace(/^data:\s*/, '').trim() + if (!trimmed || trimmed === '[DONE]') continue + try { + const data = JSON.parse(trimmed) + switch (data.type) { + case 'meta': onMeta?.(data); break + case 'assistant_chunk': + case 'outline_chunk': onChunk?.(data.content); break + case 'outline_ready': onOutlineReady?.(data); break + case 'progress': onProgress?.(data); break + case 'page_ready': onPageReady?.(data); break + case 'result_ready': onResultReady?.(data); break + case 'done': onDone?.(); break + case 'error': onError?.(data.message); break + } + } catch { /* skip non-JSON */ } + } + } +} diff --git a/teacher-platform/src/components/ppt/ChatInput.vue b/teacher-platform/src/components/ppt/ChatInput.vue new file mode 100644 index 0000000..98e2cb1 --- /dev/null +++ b/teacher-platform/src/components/ppt/ChatInput.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/teacher-platform/src/components/ppt/ChatMessage.vue b/teacher-platform/src/components/ppt/ChatMessage.vue new file mode 100644 index 0000000..999da67 --- /dev/null +++ b/teacher-platform/src/components/ppt/ChatMessage.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/teacher-platform/src/components/ppt/ChatPanel.vue b/teacher-platform/src/components/ppt/ChatPanel.vue new file mode 100644 index 0000000..5f03e1a --- /dev/null +++ b/teacher-platform/src/components/ppt/ChatPanel.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/teacher-platform/src/components/ppt/KnowledgeLibraryModal.vue b/teacher-platform/src/components/ppt/KnowledgeLibraryModal.vue new file mode 100644 index 0000000..ea1bd99 --- /dev/null +++ b/teacher-platform/src/components/ppt/KnowledgeLibraryModal.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/teacher-platform/src/components/ppt/OutlineCard.vue b/teacher-platform/src/components/ppt/OutlineCard.vue new file mode 100644 index 0000000..b25c920 --- /dev/null +++ b/teacher-platform/src/components/ppt/OutlineCard.vue @@ -0,0 +1,234 @@ + - - \ No newline at end of file From 024b49870a489e1b067e6fed3775eaac96749734 Mon Sep 17 00:00:00 2001 From: zhezhitanye-code Date: Thu, 19 Mar 2026 09:23:36 +0800 Subject: [PATCH 3/8] wip: ppt outline and preview progress --- teacher-platform/src/api/ppt.js | 46 +- .../src/components/LayoutWithNav.vue | 15 +- .../src/components/ppt/ChatInput.vue | 167 +- .../src/components/ppt/ChatMessage.vue | 200 +- .../src/components/ppt/ChatPanel.vue | 34 +- .../components/ppt/KnowledgeLibraryModal.vue | 373 ++- .../src/components/ppt/OutlineCard.vue | 489 ++-- .../src/components/ppt/PptCanvas.vue | 177 +- .../src/components/ppt/PptSidebar.vue | 135 +- .../src/components/ppt/PptThumbnailList.vue | 96 +- .../src/components/ppt/TemplateSelector.vue | 92 +- .../src/components/ppt/WelcomePanel.vue | 312 +-- teacher-platform/src/router/index.js | 6 + teacher-platform/src/utils/docmee/chart.js | 834 ++++++ .../src/utils/docmee/decodePptxProperty.js | 24 + .../src/utils/docmee/encodePptxProperty.js | 25 + teacher-platform/src/utils/docmee/geometry.js | 500 ++++ .../src/utils/docmee/ppt2canvas.js | 1328 ++++++++++ teacher-platform/src/utils/docmee/ppt2svg.js | 2265 +++++++++++++++++ teacher-platform/src/utils/pptOutlineCard.js | 202 ++ teacher-platform/src/utils/pptOutlineFlow.js | 43 + teacher-platform/src/utils/pptPreview.js | 25 + teacher-platform/src/views/LessonPrepPpt.vue | 1027 ++++++-- .../tests/ppt-chat-layout.test.mjs | 17 + .../tests/ppt-outline-card.test.mjs | 79 + .../tests/ppt-outline-flow.test.mjs | 31 + teacher-platform/tests/ppt-preview.test.mjs | 44 + 27 files changed, 7801 insertions(+), 785 deletions(-) create mode 100644 teacher-platform/src/utils/docmee/chart.js create mode 100644 teacher-platform/src/utils/docmee/decodePptxProperty.js create mode 100644 teacher-platform/src/utils/docmee/encodePptxProperty.js create mode 100644 teacher-platform/src/utils/docmee/geometry.js create mode 100644 teacher-platform/src/utils/docmee/ppt2canvas.js create mode 100644 teacher-platform/src/utils/docmee/ppt2svg.js create mode 100644 teacher-platform/src/utils/pptOutlineCard.js create mode 100644 teacher-platform/src/utils/pptOutlineFlow.js create mode 100644 teacher-platform/src/utils/pptPreview.js create mode 100644 teacher-platform/tests/ppt-chat-layout.test.mjs create mode 100644 teacher-platform/tests/ppt-outline-card.test.mjs create mode 100644 teacher-platform/tests/ppt-outline-flow.test.mjs create mode 100644 teacher-platform/tests/ppt-preview.test.mjs diff --git a/teacher-platform/src/api/ppt.js b/teacher-platform/src/api/ppt.js index fb9720d..3b8b4a4 100644 --- a/teacher-platform/src/api/ppt.js +++ b/teacher-platform/src/api/ppt.js @@ -29,12 +29,31 @@ export function getSessionDetail(sessionId) { return apiRequest(`/api/v1/ppt/sessions/${sessionId}`) } +export function deleteSession(sessionId) { + return apiRequest(`/api/v1/ppt/sessions/${sessionId}`, { method: 'DELETE' }) +} + // ========== 大纲 ========== -export function approveOutline(outlineId, content = null, imageUrls = null) { +function normalizeImageUrlsPayload(imageUrls) { + if (imageUrls == null) return null + if (Array.isArray(imageUrls)) { + return Object.fromEntries( + imageUrls + .filter(Boolean) + .map((url, index) => [String(index), url]) + ) + } + if (typeof imageUrls === 'object') return imageUrls + return null +} + +export function approveOutline(outlineId, content = null, imageUrls = null, outlinePayload = null) { const body = {} if (content !== null) body.content = content - if (imageUrls !== null) body.image_urls = imageUrls + const normalizedImageUrls = normalizeImageUrlsPayload(imageUrls) + if (normalizedImageUrls !== null) body.image_urls = normalizedImageUrls + if (outlinePayload !== null) body.outline_payload = outlinePayload return apiRequest(`/api/v1/ppt/outlines/${outlineId}/approve`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -56,6 +75,18 @@ export function saveEditSnapshot(resultId, editedPptxProperty) { }) } +export function modifyPptResult(resultId, instruction, slideIndex, currentPptxProperty) { + return apiRequest(`/api/v1/ppt/results/${resultId}/modify`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + instruction, + slide_index: slideIndex, + current_pptx_property: currentPptxProperty, + }), + }) +} + export function downloadResult(resultId) { return apiRequest(`/api/v1/ppt/results/${resultId}/download`, { method: 'POST' }) } @@ -66,6 +97,17 @@ export function getVersions(sessionId) { return apiRequest(`/api/v1/ppt/sessions/${sessionId}/versions`) } +// ========== 文件上传 ========== + +export async function uploadFile(sessionId, file) { + const formData = new FormData() + formData.append('file', file) + return authFetch(`/api/v1/ppt/sessions/${sessionId}/upload`, { + method: 'POST', + body: formData, + }).then(r => r.json()) +} + // ========== 流式请求 (fetch + reader) ========== /** diff --git a/teacher-platform/src/components/LayoutWithNav.vue b/teacher-platform/src/components/LayoutWithNav.vue index 92c7bae..32e4ca8 100644 --- a/teacher-platform/src/components/LayoutWithNav.vue +++ b/teacher-platform/src/components/LayoutWithNav.vue @@ -45,7 +45,7 @@ function isPrimaryActive(item) { } function goToPrimary(path) { - if (!path.startsWith('/lesson-prep')) lessonPrepOpen.value = false + if (!path.startsWith('/lesson-prep') && path !== '/ppt') lessonPrepOpen.value = false router.push(path) } @@ -58,12 +58,13 @@ const lessonPrepTabs = [ { id: 'data', label: '数据分析', icon: 'data' } ] -const isLessonPrepRoute = computed(() => route.path.startsWith('/lesson-prep')) +const isLessonPrepRoute = computed(() => route.path.startsWith('/lesson-prep') || route.path === '/ppt') const activeLessonPrepTab = computed(() => { + if (route.path === '/ppt') return 'ppt' const t = route.query.tab const tab = typeof t === 'string' ? t : '' const valid = lessonPrepTabs.map(i => i.id) - return valid.includes(tab) ? tab : 'ppt' + return valid.includes(tab) ? tab : 'lesson-plan' }) const lessonPrepOpen = ref(false) @@ -79,13 +80,17 @@ function toggleLessonPrep() { function goToLessonPrepTab(id) { lessonPrepOpen.value = true - router.push({ path: '/lesson-prep', query: { ...route.query, tab: id } }) + if (id === 'ppt') { + router.push('/ppt') + } else { + router.push({ path: '/lesson-prep', query: { ...route.query, tab: id } }) + } } watch( () => route.path, (p) => { - if (!p.startsWith('/lesson-prep')) lessonPrepOpen.value = false + if (!p.startsWith('/lesson-prep') && p !== '/ppt') lessonPrepOpen.value = false } ) diff --git a/teacher-platform/src/components/ppt/ChatInput.vue b/teacher-platform/src/components/ppt/ChatInput.vue index 98e2cb1..2a03d5e 100644 --- a/teacher-platform/src/components/ppt/ChatInput.vue +++ b/teacher-platform/src/components/ppt/ChatInput.vue @@ -1,25 +1,48 @@ - - - - diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue deleted file mode 100644 index 953acce..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/GeneratePpt.vue +++ /dev/null @@ -1,360 +0,0 @@ - - - - - diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue deleted file mode 100644 index 20f593c..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/OutlineEdit.vue +++ /dev/null @@ -1,194 +0,0 @@ - - - - - diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue deleted file mode 100644 index 9e961fc..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/components/SelectTemplate.vue +++ /dev/null @@ -1,179 +0,0 @@ - - - - - diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts deleted file mode 100644 index 0ac3a5f..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import './assets/main.css' - -import { createApp } from 'vue' -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js deleted file mode 100644 index 64fcd80..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/animation.js +++ /dev/null @@ -1,2903 +0,0 @@ -// 页面切场动画 -const transitionList = [ - { - name: "分割", - config: { - split: { - dir: "in", - }, - spd: "slow", - }, - key: "split", - }, - { - name: "切出", - config: { - cut: {}, - spd: "fast", - }, - key: "cut", - }, - { - name: "形状", - config: { - spd: "slow", - wedge: true, - }, - key: "wedge", - }, - { - name: "抽出", - config: { - pull: { - dir: "l", - }, - spd: "med", - }, - key: "pull", - }, - { - name: "推出", - config: { - spd: "slow", - push: { - dir: "u", - }, - }, - key: "push", - }, - { - name: "插入", - config: { - cover: { - dir: "d", - }, - spd: "slow", - }, - key: "cover", - }, - { - name: "擦除", - config: { - wipe: { - dir: "l", - }, - spd: "slow", - }, - key: "wipe", - }, - { - name: "新闻快报", - config: { - spd: "med", - newsflash: true, - }, - key: "newsflash", - }, - { - name: "梳理", - config: { - spd: "slow", - comb: { - dir: "horz", - }, - }, - key: "comb", - }, - { - name: "棋盘", - config: { - spd: "slow", - checker: { - dir: "horz", - }, - }, - key: "checker", - }, - { - name: "淡出", - config: { - fade: {}, - spd: "med", - }, - key: "fade", - }, - { - name: "溶解", - config: { - spd: "slow", - dissolve: true, - }, - key: "dissolve", - }, - { - name: "百叶窗", - config: { - blinds: { - dir: "horz", - }, - spd: "slow", - }, - key: "blinds", - }, - { - name: "线条", - config: { - spd: "slow", - randomBar: { - dir: "vert", - }, - }, - key: "randomBar", - }, - { - name: "轮幅", - config: { - spd: "slow", - wheel: { - spokes: 8, - }, - }, - key: "wheel", - }, - { - name: "随机", - config: { - random: true, - spd: "slow", - }, - key: "random", - }, -]; - -// 元素动画 -const animationList = [ - { - name: "退场动画", - children: [ - { - name: "消失", - children: [ - { - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 1, - presetSubtype: 0, - }, - ], - }, - { - name: "飞出", - children: [ - { - duration: 500, - name: "到顶部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 1, - }, - { - duration: 500, - name: "到右侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 2, - }, - { - duration: 500, - name: "到右上部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 3, - }, - { - duration: 500, - name: "到底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 4, - }, - { - duration: 500, - name: "到右下部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 6, - }, - { - duration: 500, - name: "到左侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 8, - }, - { - duration: 500, - name: "到左上部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 9, - }, - { - duration: 500, - name: "到左下部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 2, - presetSubtype: 12, - }, - ], - }, - { - name: "百叶窗", - children: [ - { - duration: 500, - name: "垂直", - startType: 1, - presetClass: "exit", - text: false, - presetId: 3, - presetSubtype: 5, - }, - { - duration: 500, - name: "水平", - startType: 1, - presetClass: "exit", - text: false, - presetId: 3, - presetSubtype: 10, - }, - ], - }, - { - name: "盒状", - children: [ - { - duration: 500, - name: "内", - startType: 1, - presetClass: "exit", - text: false, - presetId: 4, - presetSubtype: 16, - }, - { - duration: 500, - name: "外", - startType: 1, - presetClass: "exit", - text: false, - presetId: 4, - presetSubtype: 32, - }, - ], - }, - { - name: "棋盘", - children: [ - { - duration: 500, - name: "上", - startType: 1, - presetClass: "exit", - text: false, - presetId: 5, - presetSubtype: 5, - }, - { - duration: 500, - name: "跨越", - startType: 1, - presetClass: "exit", - text: false, - presetId: 5, - presetSubtype: 10, - }, - ], - }, - { - name: "圆形扩展", - children: [ - { - duration: 998, - name: "内", - startType: 1, - presetClass: "exit", - text: false, - presetId: 6, - presetSubtype: 16, - }, - { - duration: 998, - name: "外", - startType: 1, - presetClass: "exit", - text: false, - presetId: 6, - presetSubtype: 32, - }, - ], - }, - { - name: "缓慢移除", - children: [ - { - duration: 1000, - name: "到顶部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 7, - presetSubtype: 1, - }, - { - duration: 1000, - name: "到右侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 7, - presetSubtype: 2, - }, - { - duration: 1000, - name: "到底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 7, - presetSubtype: 4, - }, - { - duration: 1000, - name: "到左侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 7, - presetSubtype: 8, - }, - ], - }, - { - name: "菱形", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "exit", - text: false, - presetId: 8, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "exit", - text: false, - presetId: 8, - presetSubtype: 32, - }, - ], - }, - { - name: "向外溶解", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 9, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 10, - presetSubtype: 0, - }, - ], - }, - { - name: "闪烁一次", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 11, - presetSubtype: 0, - }, - ], - }, - { - name: "切出", - children: [ - { - duration: 500, - name: "到顶部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 12, - presetSubtype: 1, - }, - { - duration: 500, - name: "到右侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 12, - presetSubtype: 2, - }, - { - duration: 500, - name: "到底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 12, - presetSubtype: 4, - }, - { - duration: 500, - name: "到左侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 12, - presetSubtype: 8, - }, - ], - }, - { - name: "十字形扩展", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "exit", - text: false, - presetId: 13, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "exit", - text: false, - presetId: 13, - presetSubtype: 32, - }, - ], - }, - { - name: "随机线条", - children: [ - { - duration: 500, - name: "垂直", - startType: 1, - presetClass: "exit", - text: false, - presetId: 14, - presetSubtype: 5, - }, - { - duration: 500, - name: "水平", - startType: 1, - presetClass: "exit", - text: false, - presetId: 14, - presetSubtype: 10, - }, - ], - }, - { - name: "螺旋飞出", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 15, - presetSubtype: 0, - }, - ], - }, - { - name: "劈裂", - children: [ - { - duration: 500, - name: "左右向中央收缩", - startType: 1, - presetClass: "exit", - text: false, - presetId: 16, - presetSubtype: 21, - }, - { - duration: 500, - name: "上下向中央收缩", - startType: 1, - presetClass: "exit", - text: false, - presetId: 16, - presetSubtype: 26, - }, - { - duration: 500, - name: "中央向左右展开", - startType: 1, - presetClass: "exit", - text: false, - presetId: 16, - presetSubtype: 37, - }, - { - duration: 500, - name: "中央向上下展开", - startType: 1, - presetClass: "exit", - text: false, - presetId: 16, - presetSubtype: 42, - }, - ], - }, - { - name: "层叠", - children: [ - { - duration: 500, - name: "到顶部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 17, - presetSubtype: 1, - }, - { - duration: 500, - name: "到右侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 17, - presetSubtype: 2, - }, - { - duration: 500, - name: "到底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 17, - presetSubtype: 4, - }, - { - duration: 500, - name: "到左侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 17, - presetSubtype: 8, - }, - { - duration: 500, - name: "跨越", - startType: 1, - presetClass: "exit", - text: false, - presetId: 17, - presetSubtype: 10, - }, - ], - }, - { - name: "阶梯状", - children: [ - { - duration: 500, - name: "右上", - startType: 1, - presetClass: "exit", - text: false, - presetId: 18, - presetSubtype: 3, - }, - { - duration: 500, - name: "右下", - startType: 1, - presetClass: "exit", - text: false, - presetId: 18, - presetSubtype: 6, - }, - { - duration: 500, - name: "左上", - startType: 1, - presetClass: "exit", - text: false, - presetId: 18, - presetSubtype: 9, - }, - { - duration: 500, - name: "左下", - startType: 1, - presetClass: "exit", - text: false, - presetId: 18, - presetSubtype: 12, - }, - ], - }, - { - name: "旋转", - children: [ - { - duration: 999, - name: "垂直", - startType: 1, - presetClass: "exit", - text: false, - presetId: 19, - presetSubtype: 5, - }, - { - duration: 999, - name: "水平", - startType: 1, - presetClass: "exit", - text: false, - presetId: 19, - presetSubtype: 10, - }, - ], - }, - { - name: "扇形展开", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 20, - presetSubtype: 0, - }, - ], - }, - { - name: "轮子", - children: [ - { - duration: 1000, - name: "1轮幅图案", - startType: 1, - presetClass: "exit", - text: false, - presetId: 21, - presetSubtype: 1, - }, - { - duration: 1000, - name: "2轮幅图案", - startType: 1, - presetClass: "exit", - text: false, - presetId: 21, - presetSubtype: 2, - }, - { - duration: 1000, - name: "3轮幅图案", - startType: 1, - presetClass: "exit", - text: false, - presetId: 21, - presetSubtype: 3, - }, - { - duration: 1000, - name: "4轮幅图案", - startType: 1, - presetClass: "exit", - text: false, - presetId: 21, - presetSubtype: 4, - }, - { - duration: 1000, - name: "8轮幅图案", - startType: 1, - presetClass: "exit", - text: false, - presetId: 21, - presetSubtype: 8, - }, - ], - }, - { - name: "擦除", - children: [ - { - duration: 500, - name: "自顶部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 22, - presetSubtype: 1, - }, - { - duration: 500, - name: "自右侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 22, - presetSubtype: 2, - }, - { - duration: 500, - name: "自底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 22, - presetSubtype: 4, - }, - { - duration: 500, - name: "自左侧", - startType: 1, - presetClass: "exit", - text: false, - presetId: 22, - presetSubtype: 8, - }, - ], - }, - { - name: "缩放", - children: [ - { - duration: 500, - name: "内", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 16, - }, - { - duration: 500, - name: "放大到屏幕底部", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 20, - }, - { - duration: 500, - name: "外", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 32, - }, - { - duration: 500, - name: "轻微放大", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 272, - }, - { - duration: 500, - name: "轻微缩小", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 288, - }, - { - duration: 500, - name: "缩小到屏幕中心", - startType: 1, - presetClass: "exit", - text: false, - presetId: 23, - presetSubtype: 544, - }, - ], - }, - { - name: "随机效果", - children: [ - { - duration: 1, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 24, - presetSubtype: 0, - }, - ], - }, - { - name: "飞旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 25, - presetSubtype: 0, - }, - ], - }, - { - name: "弹跳", - children: [ - { - duration: 90, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 26, - presetSubtype: 0, - }, - ], - }, - { - name: "颜色打字机", - children: [ - { - name: "", - startType: 1, - presetClass: "exit", - text: true, - attr: { - dur: "50", - }, - presetId: 27, - presetSubtype: 0, - }, - ], - }, - { - name: "字幕式", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 28, - presetSubtype: 0, - }, - ], - }, - { - name: "渐出", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 29, - presetSubtype: 0, - }, - ], - }, - { - name: "浮动", - children: [ - { - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 30, - presetSubtype: 0, - }, - ], - }, - { - name: "光速", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 34, - presetSubtype: 0, - }, - ], - }, - { - name: "玩具风车", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 35, - presetSubtype: 0, - }, - ], - }, - { - name: "挥舞", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: true, - presetId: 38, - presetSubtype: 0, - }, - ], - }, - { - name: "线形", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 39, - presetSubtype: 0, - }, - ], - }, - { - name: "展开", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: true, - presetId: 40, - presetSubtype: 0, - }, - ], - }, - { - name: "挥鞭式", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: true, - presetId: 41, - presetSubtype: 0, - }, - ], - }, - { - name: "中心旋转", - children: [ - { - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 43, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变式回旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 45, - presetSubtype: 0, - }, - ], - }, - { - name: "上升", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 47, - presetSubtype: 0, - }, - ], - }, - { - name: "投掷", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 48, - presetSubtype: 0, - }, - ], - }, - { - name: "回旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 49, - presetSubtype: 0, - }, - ], - }, - { - name: "伸缩", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 50, - presetSubtype: 0, - }, - ], - }, - { - name: "放大", - children: [ - { - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 51, - presetSubtype: 0, - }, - ], - }, - { - name: "向下曲线", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 52, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变式缩放", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 53, - presetSubtype: 16, - }, - ], - }, - { - name: "滑翔", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 54, - presetSubtype: 0, - }, - ], - }, - { - name: "收缩", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 55, - presetSubtype: 0, - }, - ], - }, - { - name: "空翻", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: true, - presetId: 56, - presetSubtype: 0, - }, - ], - }, - { - name: "折叠", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "exit", - text: false, - presetId: 58, - presetSubtype: 0, - }, - ], - }, - ], - }, - { - name: "路径动画", - children: [ - { - name: "路径", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "path", - text: false, - attr: { - path: "M 0 0 L 0.25 0 E", - }, - presetId: 0, - presetSubtype: 0, - }, - ], - }, - ], - }, - { - name: "入场动画", - children: [ - { - name: "出现", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 1, - presetSubtype: 0, - }, - ], - }, - { - name: "飞入", - children: [ - { - duration: 1000, - name: "自顶部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 1, - }, - { - duration: 1000, - name: "自右侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 2, - }, - { - duration: 1000, - name: "自右上部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 3, - }, - { - duration: 1000, - name: "自底部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 4, - }, - { - duration: 1000, - name: "自右下部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 6, - }, - { - duration: 1000, - name: "自左侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 8, - }, - { - duration: 1000, - name: "自左上部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 9, - }, - { - duration: 1000, - name: "自左下部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 2, - presetSubtype: 12, - }, - ], - }, - { - name: "百叶窗", - children: [ - { - duration: 1000, - name: "垂直", - startType: 1, - presetClass: "entr", - text: false, - presetId: 3, - presetSubtype: 5, - }, - { - duration: 1000, - name: "水平", - startType: 1, - presetClass: "entr", - text: false, - presetId: 3, - presetSubtype: 10, - }, - ], - }, - { - name: "盒状", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "entr", - text: false, - presetId: 4, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "entr", - text: false, - presetId: 4, - presetSubtype: 32, - }, - ], - }, - { - name: "棋盘", - children: [ - { - duration: 1000, - name: "下", - startType: 1, - presetClass: "entr", - text: false, - presetId: 5, - presetSubtype: 5, - }, - { - duration: 1000, - name: "跨越", - startType: 1, - presetClass: "entr", - text: false, - presetId: 5, - presetSubtype: 10, - }, - ], - }, - { - name: "圆形扩展", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "entr", - text: false, - presetId: 6, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "entr", - text: false, - presetId: 6, - presetSubtype: 32, - }, - ], - }, - { - name: "缓慢进入", - children: [ - { - duration: 2000, - name: "自顶部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 7, - presetSubtype: 1, - }, - { - duration: 2000, - name: "自右侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 7, - presetSubtype: 2, - }, - { - duration: 2000, - name: "自底部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 7, - presetSubtype: 4, - }, - { - duration: 2000, - name: "自左侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 7, - presetSubtype: 8, - }, - ], - }, - { - name: "菱形", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "entr", - text: false, - presetId: 8, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "entr", - text: false, - presetId: 8, - presetSubtype: 32, - }, - ], - }, - { - name: "向内溶解", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 9, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 10, - presetSubtype: 0, - }, - ], - }, - { - name: "闪烁一次", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 11, - presetSubtype: 0, - }, - ], - }, - { - name: "切入", - children: [ - { - duration: 500, - name: "自顶部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 12, - presetSubtype: 1, - }, - { - duration: 500, - name: "自右侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 12, - presetSubtype: 2, - }, - { - duration: 500, - name: "自底部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 12, - presetSubtype: 4, - }, - { - duration: 500, - name: "自左侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 12, - presetSubtype: 8, - }, - ], - }, - { - name: "十字形扩展", - children: [ - { - duration: 1000, - name: "内", - startType: 1, - presetClass: "entr", - text: false, - presetId: 13, - presetSubtype: 16, - }, - { - duration: 1000, - name: "外", - startType: 1, - presetClass: "entr", - text: false, - presetId: 13, - presetSubtype: 32, - }, - ], - }, - { - name: "随机线条", - children: [ - { - duration: 1000, - name: "垂直", - startType: 1, - presetClass: "entr", - text: false, - presetId: 14, - presetSubtype: 5, - }, - { - duration: 1000, - name: "水平", - startType: 1, - presetClass: "entr", - text: false, - presetId: 14, - presetSubtype: 10, - }, - ], - }, - { - name: "螺旋飞入", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 15, - presetSubtype: 0, - }, - ], - }, - { - name: "劈裂", - children: [ - { - duration: 500, - name: "左右向中央收缩", - startType: 1, - presetClass: "entr", - text: false, - presetId: 16, - presetSubtype: 21, - }, - { - duration: 500, - name: "上下向中央收缩", - startType: 1, - presetClass: "entr", - text: false, - presetId: 16, - presetSubtype: 26, - }, - { - duration: 500, - name: "中央向左右展开", - startType: 1, - presetClass: "entr", - text: false, - presetId: 16, - presetSubtype: 37, - }, - { - duration: 500, - name: "中央向上下展开", - startType: 1, - presetClass: "entr", - text: false, - presetId: 16, - presetSubtype: 42, - }, - ], - }, - { - name: "伸展", - children: [ - { - duration: 500, - name: "自顶部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 17, - presetSubtype: 1, - }, - { - duration: 500, - name: "自右侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 17, - presetSubtype: 2, - }, - { - duration: 500, - name: "自底部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 17, - presetSubtype: 4, - }, - { - duration: 500, - name: "自左侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 17, - presetSubtype: 8, - }, - { - duration: 500, - name: "跨越", - startType: 1, - presetClass: "entr", - text: false, - presetId: 17, - presetSubtype: 10, - }, - ], - }, - { - name: "阶梯状", - children: [ - { - duration: 500, - name: "右上", - startType: 1, - presetClass: "entr", - text: false, - presetId: 18, - presetSubtype: 3, - }, - { - duration: 500, - name: "右下", - startType: 1, - presetClass: "entr", - text: false, - presetId: 18, - presetSubtype: 6, - }, - { - duration: 500, - name: "左上", - startType: 1, - presetClass: "entr", - text: false, - presetId: 18, - presetSubtype: 9, - }, - { - duration: 500, - name: "左下", - startType: 1, - presetClass: "entr", - text: false, - presetId: 18, - presetSubtype: 12, - }, - ], - }, - { - name: "旋转", - children: [ - { - duration: 2000, - name: "垂直", - startType: 1, - presetClass: "entr", - text: false, - presetId: 19, - presetSubtype: 5, - }, - { - duration: 2000, - name: "水平", - startType: 1, - presetClass: "entr", - text: false, - presetId: 19, - presetSubtype: 10, - }, - ], - }, - { - name: "扇形展开", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 20, - presetSubtype: 0, - }, - ], - }, - { - name: "轮子", - children: [ - { - duration: 1000, - name: "1轮幅图案", - startType: 1, - presetClass: "entr", - text: false, - presetId: 21, - presetSubtype: 1, - }, - { - duration: 1000, - name: "2轮幅图案", - startType: 1, - presetClass: "entr", - text: false, - presetId: 21, - presetSubtype: 2, - }, - { - duration: 1000, - name: "3轮幅图案", - startType: 1, - presetClass: "entr", - text: false, - presetId: 21, - presetSubtype: 3, - }, - { - duration: 1000, - name: "4轮幅图案", - startType: 1, - presetClass: "entr", - text: false, - presetId: 21, - presetSubtype: 4, - }, - { - duration: 1000, - name: "8轮幅图案", - startType: 1, - presetClass: "entr", - text: false, - presetId: 21, - presetSubtype: 8, - }, - ], - }, - { - name: "擦除", - children: [ - { - duration: 500, - name: "自顶部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 22, - presetSubtype: 1, - }, - { - duration: 500, - name: "自右侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 22, - presetSubtype: 2, - }, - { - duration: 500, - name: "自底部", - startType: 1, - presetClass: "entr", - text: false, - presetId: 22, - presetSubtype: 4, - }, - { - duration: 500, - name: "自左侧", - startType: 1, - presetClass: "entr", - text: false, - presetId: 22, - presetSubtype: 8, - }, - ], - }, - { - name: "缩放", - children: [ - { - duration: 500, - name: "内", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 16, - }, - { - duration: 500, - name: "外", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 32, - }, - { - duration: 500, - name: "从屏幕底部缩小", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 36, - }, - { - duration: 500, - name: "轻微放大", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 272, - }, - { - duration: 500, - name: "轻微缩小", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 288, - }, - { - duration: 500, - name: "从屏幕中心放大", - startType: 1, - presetClass: "entr", - text: false, - presetId: 23, - presetSubtype: 528, - }, - ], - }, - { - name: "随机效果", - children: [ - { - duration: 1, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 24, - presetSubtype: 0, - }, - ], - }, - { - name: "飞旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 25, - presetSubtype: 0, - }, - ], - }, - { - name: "弹跳", - children: [ - { - duration: 290, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 26, - presetSubtype: 0, - }, - ], - }, - { - name: "颜色打字机", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: true, - attr: { - dur: "50", - }, - presetId: 27, - presetSubtype: 0, - }, - ], - }, - { - name: "字幕式", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 28, - presetSubtype: 0, - }, - ], - }, - { - name: "渐入", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 29, - presetSubtype: 0, - }, - ], - }, - { - name: "浮动", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 30, - presetSubtype: 0, - }, - ], - }, - { - name: "旋转式由远及近", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 31, - presetSubtype: 0, - }, - ], - }, - { - name: "光速", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 34, - presetSubtype: 0, - }, - ], - }, - { - name: "玩具风车", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 35, - presetSubtype: 0, - }, - ], - }, - { - name: "升起", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 37, - presetSubtype: 0, - }, - ], - }, - { - name: "挥舞", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: true, - presetId: 38, - presetSubtype: 0, - }, - ], - }, - { - name: "线形", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 39, - presetSubtype: 0, - }, - ], - }, - { - name: "展开", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: true, - presetId: 40, - presetSubtype: 0, - }, - ], - }, - { - name: "挥鞭式", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: true, - presetId: 41, - presetSubtype: 0, - }, - ], - }, - { - name: "上升", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 42, - presetSubtype: 0, - }, - ], - }, - { - name: "中心旋转", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 43, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变式回旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 45, - presetSubtype: 0, - }, - ], - }, - { - name: "下降", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 47, - presetSubtype: 0, - }, - ], - }, - { - name: "投掷", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 48, - presetSubtype: 0, - }, - ], - }, - { - name: "回旋", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 49, - presetSubtype: 0, - }, - ], - }, - { - name: "压缩", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 50, - presetSubtype: 0, - }, - ], - }, - { - name: "放大", - children: [ - { - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 51, - presetSubtype: 0, - }, - ], - }, - { - name: "曲线向上", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 52, - presetSubtype: 0, - }, - ], - }, - { - name: "渐变式缩放", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 53, - presetSubtype: 16, - }, - ], - }, - { - name: "滑翔", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 54, - presetSubtype: 0, - }, - ], - }, - { - name: "展开", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 55, - presetSubtype: 0, - }, - ], - }, - { - name: "空翻", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: true, - presetId: 56, - presetSubtype: 0, - }, - ], - }, - { - name: "折叠", - children: [ - { - duration: 1000, - name: "", - startType: 1, - presetClass: "entr", - text: false, - presetId: 58, - presetSubtype: 0, - }, - ], - }, - ], - }, - { - name: "强调动画", - children: [ - { - name: "更改填充颜色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - attr: { - scheme: "accent2", - }, - presetId: 1, - presetSubtype: 2, - }, - ], - }, - { - name: "更改字体", - children: [ - { - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - font: "黑体", - }, - presetId: 2, - presetSubtype: 0, - }, - ], - }, - { - name: "更改字体颜色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - scheme: "accent2", - }, - presetId: 3, - presetSubtype: 2, - }, - ], - }, - { - name: "更改字号", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - fontSize: "1.5", - }, - presetId: 4, - presetSubtype: 2, - }, - ], - }, - { - name: "更改字形", - children: [ - { - duration: 2000, - name: "无", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 0, - }, - { - duration: 2000, - name: "加粗", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 1, - }, - { - duration: 2000, - name: "斜体", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 2, - }, - { - duration: 2000, - name: "加粗斜体", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 3, - }, - { - duration: 2000, - name: "下划线", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 4, - }, - { - duration: 2000, - name: "加粗下划线", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 5, - }, - { - duration: 2000, - name: "斜体下划线", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 6, - }, - { - duration: 2000, - name: "加粗斜体下划线", - startType: 1, - presetClass: "emph", - text: true, - presetId: 5, - presetSubtype: 7, - }, - ], - }, - { - name: "放大缩小", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 6, - presetSubtype: 0, - }, - ], - }, - { - name: "更改线条颜色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - attr: { - scheme: "accent2", - }, - presetId: 7, - presetSubtype: 2, - }, - ], - }, - { - name: "陀螺旋", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 8, - presetSubtype: 0, - }, - ], - }, - { - name: "透明", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 9, - presetSubtype: 0, - }, - ], - }, - { - name: "加粗闪烁", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - presetId: 10, - presetSubtype: 0, - }, - ], - }, - { - name: "爆炸", - children: [ - { - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 14, - presetSubtype: 0, - }, - ], - }, - { - name: "加粗展示", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - presetId: 15, - presetSubtype: 0, - }, - ], - }, - { - name: "着色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - scheme: "accent2", - }, - presetId: 16, - presetSubtype: 0, - }, - ], - }, - { - name: "添加下划线", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - presetId: 18, - presetSubtype: 0, - }, - ], - }, - { - name: "混色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - attr: { - scheme: "accent2", - }, - presetId: 19, - presetSubtype: 0, - }, - ], - }, - { - name: "彩色波纹", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - scheme: "accent2", - }, - presetId: 20, - presetSubtype: 0, - }, - ], - }, - { - name: "补色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 21, - presetSubtype: 0, - }, - ], - }, - { - name: "补色2", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 22, - presetSubtype: 0, - }, - ], - }, - { - name: "对比色", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 23, - presetSubtype: 0, - }, - ], - }, - { - name: "加深", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 24, - presetSubtype: 0, - }, - ], - }, - { - name: "不饱和", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 25, - presetSubtype: 0, - }, - ], - }, - { - name: "忽明忽暗", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 26, - presetSubtype: 0, - }, - ], - }, - { - name: "闪动", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 27, - presetSubtype: 0, - }, - ], - }, - { - name: "颜色延伸", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - scheme: "accent2", - }, - presetId: 28, - presetSubtype: 0, - }, - ], - }, - { - name: "变淡", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 30, - presetSubtype: 0, - }, - ], - }, - { - name: "样式强调", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - attr: { - scheme: "accent2", - }, - presetId: 31, - presetSubtype: 0, - }, - ], - }, - { - name: "跷跷板", - children: [ - { - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 32, - presetSubtype: 0, - }, - ], - }, - { - name: "垂直突出显示", - children: [ - { - duration: 1500, - name: "", - startType: 1, - presetClass: "emph", - text: false, - attr: { - scheme: "accent2", - }, - presetId: 33, - presetSubtype: 0, - }, - ], - }, - { - name: "波浪线", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - presetId: 34, - presetSubtype: 0, - }, - ], - }, - { - name: "闪烁", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: false, - presetId: 35, - presetSubtype: 0, - }, - ], - }, - { - name: "闪现", - children: [ - { - duration: 2000, - name: "", - startType: 1, - presetClass: "emph", - text: true, - presetId: 36, - presetSubtype: 0, - }, - ], - }, - ], - }, -] - -export { transitionList, animationList } diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js deleted file mode 100644 index 8a52ade..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/chart.js +++ /dev/null @@ -1,834 +0,0 @@ -async function drawChart(chart, anchor, canvas, ctx) { - if (!canvas) { - canvas = document.createElement('canvas') - let width = anchor[2] - let height = anchor[3] - canvas.width = width * 2 - canvas.height = height * 2 - canvas.style.width = width + 'px' - canvas.style.height = height + 'px' - let ctx = canvas.getContext('2d') - ctx.scale(2, 2) - ctx.imageSmoothingEnabled = true - ctx.imageSmoothingQuality = 'high' - } - if (!ctx) { - ctx = canvas.getContext('2d') - } - ctx.imageSmoothingEnabled = true - ctx.imageSmoothingQuality = 'high' - let title = chart.title - let legend = chart.legend - let chartData = chart.chartData[0] - let chartType = chartData.chartType - if (chartType == 'bar') { - // 柱状图、条形图 - let type = chartData.extInfo.type - if (type == 'bar') { - // 条形图 - await drawBarChartWithBar(title, chartData, legend, anchor, canvas, ctx) - } else { - // 柱状图 - await drawBarChartWithCol(title, chartData, legend, anchor, canvas, ctx) - } - } else if (chartType == 'pie' || chartType == 'doughnut') { - // 饼图、圆环图 - await drawPieChart(title, chartData, legend, anchor, canvas, ctx) - } else if (chartType == 'line') { - // 折线图 - await drawLineChart(title, chartData, legend, anchor, canvas, ctx) - } else { - // 其他: 暂不支持 - await drawRect(ctx, { - strokeStyle: { - lineWidth: 0.5, - paint: { type: 'color', color: { color: -2500135 } } - }, - anchor: [anchor[0] + 0.5, anchor[1] + 0.5, anchor[2] - 1, anchor[3] - 1] - }) - let str = '该图表暂不支持渲染' - ctx.font = `${Math.min(anchor[2] * 0.056, 16)}px 等线` - ctx.fillStyle = 'rgb(153, 153, 153)' - let textWidth = ctx.measureText(str).width - ctx.fillText(str, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] / 2 - 8) - } - return canvas -} - -async function drawBarChartWithBar(title, chartData, legend, anchor, canvas, ctx) { - if (title) { - ctx.font = `${Math.min(anchor[3] * 0.064, 18.5)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - let textWidth = ctx.measureText(title).width - ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) - } - let extInfo = chartData.extInfo - let series = chartData.series - let categoryAxis = chartData.categoryAxis - let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null - let minValue = 0, maxValue = 0 - for (let i = 0; i < series.length; i++) { - minValue = Math.min(minValue, ...series[i].value.data) - maxValue = Math.max(maxValue, ...series[i].value.data) - } - ctx.lineWidth = 0.5 - ctx.font = `${Math.min(anchor[2] * 0.048, 14)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.strokeStyle = 'rgb(217, 217, 217)' - let categorys = series[0].category.data - let maxCw = ctx.measureText('00').width - for (let i = 0; i < categorys.length; i++) { - let w = ctx.measureText(categorys[i] + '0').width - if (w > maxCw) { - maxCw = w - } - } - let sGap = valueAxes && !valueAxes.deleted ? maxCw : anchor[2] * 0.15 - let x = anchor[0] + sGap - let xWidth = anchor[2] - sGap - anchor[2] * 0.04 - let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 - let y = anchor[1] + startY - let yHeight = anchor[3] - startY - anchor[3] * 0.15 - let minTicks = xWidth / 10 > 20 ? 11 : 6 - let ticks = calculateTicks(minValue, maxValue, minTicks, 11) - let xGap = xWidth / (ticks.length - 1) - ctx.beginPath() - for (let i = 0; i < ticks.length; i++) { - // x轴数值 - if (valueAxes && !valueAxes.deleted) { - ctx.textAlign = 'center' - let v = ticks[i] - let vs = v.toString() - if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { - vs = v.toFixed(1) - } - ctx.fillText(vs, x, y + yHeight + anchor[3] * 0.05) - ctx.textAlign = 'start' - } - if (extInfo.majorGridlines == 'true') { - // 网格线 - ctx.moveTo(x, y) - ctx.lineTo(x, y + yHeight) - } - x += xGap - } - ctx.stroke() - let yGap = anchor[3] * 0.04 // y开始 - y += yGap - x = anchor[0] + sGap - let vGap = anchor[3] * 0.015 // 柱子间距 - let catGap = vGap * 5 // 类目间距 - let categoryHeight = (yHeight - catGap * (categorys.length - 1) - yGap * 2) / categorys.length - let vHeight = (categoryHeight - vGap * (series.length - 1)) / series.length - // 绘制类目和柱状图 - for (let i = 0; i < categorys.length; i++) { - if (categoryAxis && !categoryAxis.deleted) { - ctx.fillStyle = 'rgb(89, 89, 89)' - let _cy = (categoryHeight + catGap) * i + categoryHeight / 2 + 6 - ctx.textAlign = 'right' - ctx.fillText(categorys[categorys.length - 1 - i], x - 4, y + _cy) - ctx.textAlign = 'start' - } - for (let j = 0; j < series.length; j++) { - let seriesData = series[series.length - 1 - j] - let valueData = seriesData.value.data - let vWidth = (valueData[valueData.length - 1 - i] / ticks[ticks.length - 1]) * xWidth - let _x = x - let _y = y + (categoryHeight + catGap) * i + (vHeight + vGap) * j - let _anchor = [_x, _y, vWidth, vHeight] - // 柱状图 - await drawRect(ctx, { - fillStyle: seriesData.property.fillStyle, - strokeStyle: seriesData.property.strokeStyle, - anchor: _anchor - }) - } - } - if (legend) { - // 绘制v标签标识 - x = anchor[0] + sGap - let vTexts = [] - let vTextWidth = 0 - for (let i = 0; i < series.length; i++) { - let s = series[i].text.data[0] - vTexts.push(s) - vTextWidth += ctx.measureText(s).width - } - vGap = anchor[3] * 0.03 - let _iw = Math.min(anchor[2] * 0.028, 15) - let _y = y + yHeight + anchor[3] * 0.1 - let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 - for (let i = 0; i < vTexts.length; i++) { - await drawRect(ctx, { - fillStyle: series[series.length - 1 - i].property.fillStyle, - strokeStyle: series[series.length - 1 - i].property.strokeStyle, - anchor: [_x, _y - _iw, _iw, _iw] - }) - _x += (_iw * 1.25) - ctx.fillStyle = 'rgb(89, 89, 89)' - let str = vTexts[vTexts.length - 1 - i] - ctx.fillText(str, _x, _y) - _x += ctx.measureText(str).width - _x += vGap - } - } -} - -async function drawBarChartWithCol(title, chartData, legend, anchor, canvas, ctx) { - if (title) { - ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - let textWidth = ctx.measureText(title).width - ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) - } - let extInfo = chartData.extInfo - let series = chartData.series - let categoryAxis = chartData.categoryAxis - let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null - let minValue = 0, maxValue = 0 - for (let i = 0; i < series.length; i++) { - minValue = Math.min(minValue, ...series[i].value.data) - maxValue = Math.max(maxValue, ...series[i].value.data) - } - ctx.lineWidth = 0.5 - ctx.font = `${Math.min(anchor[3] * 0.06, 14)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.strokeStyle = 'rgb(217, 217, 217)' - let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 - let y = anchor[1] + startY - let yHeight = anchor[3] - startY - anchor[3] * 0.15 - let mixTicks = yHeight / 10 > 20 ? 11 : 6 - let ticks = calculateTicks(minValue, maxValue, mixTicks, 11) - let xGap = ctx.measureText(ticks[ticks.length - 1] + '00').width - let x = anchor[0] + xGap - let xWidth = anchor[2] - xGap * 1.5 - let yGap = yHeight / (ticks.length - 1) - ctx.beginPath() - for (let i = 0; i < ticks.length; i++) { - if (valueAxes && !valueAxes.deleted) { - // y轴数值 - ctx.textAlign = 'right' - let v = ticks[ticks.length - 1 - i] - let vs = v.toString() - if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { - vs = v.toFixed(1) - } - ctx.fillText(vs, x - 4, y + 6) - ctx.textAlign = 'start' - } - if (extInfo.majorGridlines == 'true') { - // 网格线 - ctx.moveTo(x, y) - ctx.lineTo(x + xWidth, y) - } - y += yGap - } - ctx.stroke() - x += xGap - y -= yGap - let vGap = anchor[2] * 0.01 // 柱子间距 - let catGap = vGap * 6 // 类目间距 - let categorys = series[0].category.data - let categoryWidth = (xWidth - catGap * (categorys.length - 1) - xGap * 1.5) / categorys.length - let vWidth = (categoryWidth - vGap * (series.length - 1)) / series.length - // 绘制类目和柱状图 - for (let i = 0; i < categorys.length; i++) { - if (categoryAxis && !categoryAxis.deleted) { - let _cx = (categoryWidth + catGap) * i + categoryWidth / 2 - ctx.measureText(categorys[i]).width / 2 - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.fillText(categorys[i], x + _cx, y + anchor[3] * 0.055) - } - for (let j = 0; j < series.length; j++) { - let vHeight = (series[j].value.data[i] / ticks[ticks.length - 1]) * yHeight - let _x = x + (categoryWidth + catGap) * i + (vWidth + vGap) * j - let _y = y - vHeight - let _anchor = [_x, _y, vWidth, vHeight] - // 柱状图 - await drawRect(ctx, { - fillStyle: series[j].property.fillStyle, - strokeStyle: series[j].property.strokeStyle, - anchor: _anchor - }) - } - } - if (legend) { - // 绘制v标签标识 - x = anchor[0] + xGap - let vTexts = [] - let vTextWidth = 0 - for (let i = 0; i < series.length; i++) { - let s = series[i].text.data[0] - vTexts.push(s) - vTextWidth += ctx.measureText(s).width - } - vGap = anchor[2] * 0.02 - let _iw = Math.min(anchor[2] * 0.025, 15) - let _y = y + anchor[3] * 0.125 - let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 - for (let i = 0; i < vTexts.length; i++) { - await drawRect(ctx, { - fillStyle: series[i].property.fillStyle, - strokeStyle: series[i].property.strokeStyle, - anchor: [_x, _y - _iw, _iw, _iw] - }) - _x += (_iw * 1.25) - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.fillText(vTexts[i], _x, _y) - _x += ctx.measureText(vTexts[i]).width - _x += vGap - } - } -} - -async function drawPieChart(title, chartData, legend, anchor, canvas, ctx) { - if (title == '') { - title = chartData.series[0].text.data[0] - } - if (title) { - ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - let textWidth = ctx.measureText(title).width - ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) - } - let extInfo = chartData.extInfo - let holeSize = +(extInfo.holeSize || 0) / 100 - let series = chartData.series - let values = series[0].value.data - let dataPoints = series[0].dataPoint - let totalValue = 0 - for (let i = 0; i < values.length; i++) { - totalValue += (+values[i]) - } - let xGap = anchor[2] * 0.05 // 开始间距 - let x = anchor[0] + xGap - let xWidth = anchor[2] - xGap * 2 - let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 - let y = anchor[1] + startY - let yHeight = anchor[3] - startY - anchor[3] * 0.15 - let centerX = xWidth / 2 - let centerY = yHeight / 2 - let radius = Math.min(centerX, centerY) - ctx.lineWidth = 0.5 - ctx.font = `${Math.min(anchor[2] * 0.048, 14)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.save() - ctx.translate(x + centerX, y + centerY) - // arc 是以3点钟方向开始,反向旋转-90调整到0点开始 - ctx.rotate(-90 * Math.PI / 180) - ctx.translate(-x - centerX, -y - centerY) - let startAngle = 0 - if (extInfo.startAngle) { - startAngle = extInfo.startAngle * (Math.PI / 180) - } - for (let i = 0; i < values.length; i++) { - let property = dataPoints[i].property - ctx.fillStyle = await toCtxPaint(ctx, property.fillStyle, property.anchor || anchor) - if (property.strokeStyle) { - ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 - let lineCap = property.strokeStyle.lineCap - if (!lineCap || lineCap == 'FLAT') { - lineCap = 'butt' - } - ctx.lineCap = lineCap.toLowerCase() - ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor || anchor) - } - let sliceAngle = (2 * Math.PI * values[i]) / totalValue - ctx.beginPath() - ctx.moveTo(x + centerX, y + centerY) - // 实心圆 - ctx.arc(x + centerX, y + centerY, radius, startAngle, startAngle + sliceAngle, false) - if (holeSize > 0) { - // 空心圆 - let holeRadius = radius * holeSize - ctx.arc(x + centerX, y + centerY, holeRadius, startAngle + sliceAngle, startAngle, true) - ctx.closePath() - ctx.save() - ctx.clip() - ctx.fill() - ctx.stroke() - ctx.restore() - } else { - ctx.closePath() - ctx.fill() - ctx.stroke() - } - startAngle += sliceAngle - } - ctx.restore() - if (legend) { - // 绘制类目标签标识 - let vTexts = [] - let vTextWidth = 0 - let categorys = series[0].category.data - for (let i = 0; i < categorys.length; i++) { - let s = categorys[i] - vTexts.push(s) - vTextWidth += ctx.measureText(s).width - } - let vGap = anchor[2] * 0.03 - let _iw = Math.min(anchor[2] * 0.028, 15) - let _y = y + yHeight + anchor[3] * 0.125 - let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw * 1.25) * vTexts.length) / 2 - for (let i = 0; i < vTexts.length; i++) { - let property = dataPoints[i].property - await drawRect(ctx, { - fillStyle: property.fillStyle, - strokeStyle: property.strokeStyle, - anchor: [_x, _y - _iw, _iw, _iw] - }) - _x += (_iw * 1.25) - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.fillText(vTexts[i], _x, _y) - _x += ctx.measureText(vTexts[i]).width - _x += vGap - } - } -} - -async function drawLineChart(title, chartData, legend, anchor, canvas, ctx) { - if (title) { - ctx.font = `${Math.min(anchor[3] * 0.07, 18.5)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - let textWidth = ctx.measureText(title).width - ctx.fillText(title, anchor[0] + anchor[2] / 2 - textWidth / 2, anchor[1] + anchor[3] * 0.06) - } - let extInfo = chartData.extInfo - let smooth = extInfo.smooth == 'true' - let series = chartData.series - let categoryAxis = chartData.categoryAxis - let valueAxes = chartData.valueAxes && chartData.valueAxes.length > 0 ? chartData.valueAxes[0] : null - let minValue = 0, maxValue = 0 - for (let i = 0; i < series.length; i++) { - minValue = Math.min(minValue, ...series[i].value.data) - maxValue = Math.max(maxValue, ...series[i].value.data) - } - ctx.lineWidth = 0.5 - ctx.font = `${Math.min(anchor[3] * 0.06, 14)}px 等线` - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.strokeStyle = 'rgb(217, 217, 217)' - let ticks = calculateTicks(minValue, maxValue, 5, 10) - let xGap = ctx.measureText(ticks[ticks.length - 1] + '00').width - let x = anchor[0] + xGap - let xWidth = anchor[2] - xGap * 1.5 - let startY = title ? anchor[3] * 0.12 : anchor[3] * 0.05 - let y = anchor[1] + startY - let yHeight = anchor[3] - startY - anchor[3] * 0.15 - let yGap = yHeight / (ticks.length - 1) - ctx.beginPath() - for (let i = 0; i < ticks.length; i++) { - // y轴数值 - if (valueAxes && !valueAxes.deleted) { - ctx.textAlign = 'right' - let v = ticks[ticks.length - 1 - i] - let vs = v.toString() - if (vs.indexOf('.') > -1 && vs.split('.')[1].length > 1) { - vs = v.toFixed(1) - } - ctx.fillText(vs, x - 4, y + 6) - ctx.textAlign = 'start' - } - if (extInfo.majorGridlines == 'true') { - // 网格线 - ctx.moveTo(x, y) - ctx.lineTo(x + xWidth, y) - } - y += yGap - } - ctx.stroke() - x += xGap - y -= yGap - let catGap = anchor[2] * 0.05 // 类目间距 - let categorys = series[0].category.data - let categoryWidth = (xWidth - catGap * (categorys.length - 1) - xGap * 1.5) / categorys.length - let cxList = [] - // 绘制类目 - for (let i = 0; i < categorys.length; i++) { - let _cx = (categoryWidth + catGap) * i + categoryWidth / 2 - ctx.measureText(categorys[i]).width / 2 - cxList.push(_cx) - if (categoryAxis && !categoryAxis.deleted) { - ctx.textAlign = 'center' - ctx.fillText(categorys[i], x + _cx, y + anchor[3] * 0.05) - ctx.textAlign = 'start' - } - } - // 绘制折线 - for (let i = 0; i < series.length; i++) { - let property = series[i].property - if (property.strokeStyle) { - ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 - let lineCap = property.strokeStyle.lineCap - if (!lineCap || lineCap == 'FLAT') { - lineCap = 'butt' - } - ctx.lineCap = lineCap.toLowerCase() - ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) - } - ctx.beginPath() - let points = [] - for (let j = 0; j < categorys.length; j++) { - let vHeight = (series[i].value.data[j] / ticks[ticks.length - 1]) * yHeight - let _x = x + cxList[j] - let _y = y - vHeight - if (j == 0) { - ctx.moveTo(_x, _y) - } else if (smooth) { - points.push({ x: _x, y: _y }) - } else { - ctx.lineTo(_x, _y) - } - } - if (smooth) { - let j = 0 - for (; j < points.length - 2; j++) { - let xc = (points[j].x + points[j + 1].x) / 2 - let yc = (points[j].y + points[j + 1].y) / 2 - ctx.quadraticCurveTo(points[j].x, points[j].y, xc, yc) - } - ctx.quadraticCurveTo(points[j].x, points[j].y, points[j + 1].x, points[j + 1].y) - } - ctx.stroke() - } - if (legend) { - // 绘制v标签标识 - x = anchor[0] + xGap - let vTexts = [] - let vTextWidth = 0 - for (let i = 0; i < series.length; i++) { - let s = series[i].text.data[0] - vTexts.push(s) - vTextWidth += ctx.measureText(s).width - } - let vGap = anchor[2] * 0.02 - let _iw = anchor[2] * 0.04 - let _y = y + anchor[3] * 0.128 - let _x = x + xWidth / 2 - (vTextWidth + vGap * (vTexts.length - 1) + (_iw + 2) * vTexts.length) / 2 - for (let i = 0; i < vTexts.length; i++) { - let property = series[i].property - if (property.strokeStyle) { - ctx.lineWidth = property.strokeStyle.lineWidth || 1.5 - let lineCap = property.strokeStyle.lineCap - if (!lineCap || lineCap == 'FLAT') { - lineCap = 'butt' - } - ctx.lineCap = lineCap.toLowerCase() - ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) - } - ctx.beginPath() - ctx.moveTo(_x, _y - 4) - ctx.lineTo(_x + _iw, _y - 4) - ctx.stroke() - _x += (_iw + 2) - ctx.fillStyle = 'rgb(89, 89, 89)' - ctx.fillText(vTexts[i], _x, _y) - _x += ctx.measureText(vTexts[i]).width - _x += vGap - } - } -} - -function calculateTicks(minValue, maxValue, minTicks, maxTicks) { - let range = maxValue - minValue - let rawInterval = range / (minTicks - 1) - let magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval))) - let normalizedInterval = rawInterval / magnitude - let adjustedInterval - if (normalizedInterval <= 1.5) { - adjustedInterval = 1 - } else if (normalizedInterval <= 3) { - adjustedInterval = 2 - } else if (normalizedInterval <= 7) { - adjustedInterval = 5 - } else { - adjustedInterval = 10 - } - adjustedInterval *= magnitude - let tickEnd = Math.ceil(maxValue / adjustedInterval) * adjustedInterval - let ticks = [] - for (let tick = 0; tick <= tickEnd; tick += adjustedInterval) { - ticks.push(tick) - } - if (ticks.length < minTicks) { - for (let i = ticks.length; i < minTicks; i++) { - ticks.push(i * adjustedInterval) - } - } else { - while (ticks.length > maxTicks) { - adjustedInterval *= 2 - ticks = [] - tickEnd = Math.ceil(maxValue / adjustedInterval) * adjustedInterval - for (let tick = 0; tick <= tickEnd; tick += adjustedInterval) { - ticks.push(tick) - } - } - } - return ticks -} - -async function drawRect(ctx, property) { - ctx.fillStyle = await toCtxPaint(ctx, property.fillStyle, property.anchor) - if (property.strokeStyle) { - ctx.lineWidth = property.strokeStyle.lineWidth || 1 - ctx.strokeStyle = await toCtxPaint(ctx, property.strokeStyle.paint, property.anchor) - } - ctx.fillRect(property.anchor[0], property.anchor[1], property.anchor[2], property.anchor[3]) -} - -function toCtxPaint(ctx, paint, anchor, isBackground, defaultColor) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - return new Promise((resolve, reject) => { - if (!paint) { - resolve(defaultColor || 'transparent') - } else if (paint.type == 'noFill') { - // 无填充 - resolve('transparent') - } else if (paint.type == 'color') { - // 颜色 - resolve(toColor(paint.color, defaultColor)) - } else if (paint.type == 'bgFill') { - // 背景填充 - resolve(ctx.bgFillStyle || defaultColor || 'transparent') - } else if (paint.type == 'groupFill') { - // 组合背景 - let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle - if (groupFillStyle) { - toCtxPaint(ctx, groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { - resolve(res) - }) - } else { - resolve(defaultColor || 'transparent') - } - } else if (paint.type == 'gradient') { - // 渐变 - let gradient = paint.gradient - let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] - let centerX = x + width / 2 - let centerY = y + height / 2 - let gradientObj - // linear,circular,rectangular,shape - if (gradient.gradientType == 'circular') { - // 射线 - let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) - let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 - let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 - gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) - } else { - // 线性 - let startX = x - let startY = centerY - let endX = x + width - let endY = centerY - if (gradient.angle) { - let radians = gradient.angle * Math.PI / 180 - let midX = (startX + endX) / 2 - let midY = (startY + endY) / 2 - let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) - let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) - let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) - let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) - startX = newStartX - startY = newStartY - endX = newEndX - endY = newEndY - } - gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) - } - for (let i = 0; i < gradient.colors.length; i++) { - let color = gradient.colors[i] - gradientObj.addColorStop(gradient.fractions[i], toColor(color)) - } - resolve(gradientObj) - } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { - resolve('transparent') - } else if (paint.type == 'texture') { - // 图片或纹理 - let texture = paint.texture - loadChartImage(texture.imageData).then(img => { - let pat = createCtxTexturePattern(ctx, img, texture, anchor) - resolve(pat) - }) - } else if (paint.type == 'pattern') { - // 图案 - let pattern = paint.pattern - // let prst = pattern.prst - let fgColor = pattern.fgColor.realColor - let bgColor = pattern.bgColor.realColor - let width = anchor[2], height = anchor[3] - let imgCanvas = document.createElement('canvas') - imgCanvas.width = width - imgCanvas.height = height - let imgCtx = imgCanvas.getContext('2d') - imgCtx.imageSmoothingEnabled = true - imgCtx.imageSmoothingQuality = 'high' - let imgData = imgCtx.createImageData(width, height) - let line = 0 - for (let i = 0; i < imgData.data.length; i += 4) { - if (++line % 16 == 0) { - // 前景 - imgData.data[i + 0] = (fgColor >> 16) & 255 - imgData.data[i + 1] = (fgColor >> 8) & 255 - imgData.data[i + 2] = (fgColor >> 0) & 255 - imgData.data[i + 3] = (fgColor >> 24) & 255 - } else { - // 背景 - imgData.data[i + 0] = (bgColor >> 16) & 255 - imgData.data[i + 1] = (bgColor >> 8) & 255 - imgData.data[i + 2] = (bgColor >> 0) & 255 - imgData.data[i + 3] = (bgColor >> 24) & 255 - } - if (i % 400 == 0) { - line += 2 - } - } - imgCtx.putImageData(imgData, 0, 0) - let imgSrc = imgCanvas.toDataURL() - let image = new Image() - image.src = imgSrc - image.onload = async function() { - resolve(ctx.createPattern(image, 'no-repeat')) - } - } - }) -} - -function createCtxTexturePattern(ctx, img, texture, anchor) { - let width = anchor[2] - let height = anchor[3] - let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' - if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { - return ctx.createPattern(img, mode) - } - if (texture.alignment || !texture.stretch) { - width = img.width - height = img.height - } - let patternCanvas = document.createElement('canvas') - patternCanvas.width = Math.max(1, width) - patternCanvas.height = Math.max(1, height) - let patternCtx = patternCanvas.getContext('2d') - patternCtx.imageSmoothingEnabled = true - patternCtx.imageSmoothingQuality = 'high' - if (texture.alpha >= 0 && texture.alpha < 100000) { - patternCtx.globalAlpha = texture.alpha / 100000 - } - let imgInsets = null - if (texture.insets) { - let top = texture.insets[0] / 100000 - let left = texture.insets[1] / 100000 - let bottom = texture.insets[2] / 100000 - let right = texture.insets[3] / 100000 - let x = img.width * left - let y = img.height * top - let w = img.width * (1 - left - right) - let h = img.height * (1 - top - bottom) - imgInsets = [x, y, w, h] - } - if (texture.stretch) { - let top = texture.stretch[0] / 100000 - let left = texture.stretch[1] / 100000 - let bottom = texture.stretch[2] / 100000 - let right = texture.stretch[3] / 100000 - let x = width * left - let y = height * top - let w = width * (1 - left - right) - let h = height * (1 - top - bottom) - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) - } else { - patternCtx.drawImage(img, x, y, w, h) - } - } else if (texture.alignment) { - let x = 0, y = 0 - if (texture.alignment == 'CENTER') { - if (width > anchor[2]) { - x = (width - anchor[2]) / 2 - } - if (height > anchor[3]) { - y = (height - anchor[3]) / 2 - } - } - patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) - } else { - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) - } else { - patternCtx.drawImage(img, 0, 0, width, height) - } - } - if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { - // 重新着色 - let color = texture.duoTone[0].realColor - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) - let data = imageData.data - for(var i = 0; i < data.length; i += 4) { - let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 - // black / white - let prst = texture.duoTonePrst == 'white' ? 255 : 0 - data[i] = gray * r + (1 - gray) * prst - data[i + 1] = gray * g + (1 - gray) * prst - data[i + 2] = gray * b + (1 - gray) * prst - } - patternCtx.putImageData(imageData, 0, 0) - } - return ctx.createPattern(patternCanvas, mode) -} - -function toColor(colorObj, defaultColor) { - if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { - return defaultColor || 'transparent' - } - let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let a = ((color >> 24) & 255) / 255 - if (colorObj.realColor == null) { - if (colorObj.alpha != null && colorObj.alpha != -1) { - if (colorObj.alpha > 1000) { - a = colorObj.alpha / 100000 - } else { - a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 - } - a = Math.min(1, Math.max(0, a)) - } - if (colorObj.lumMod && colorObj.lumMod > 0) { - let value = colorObj.lumMod / 100000 - r = r * value - g = g * value - b = b * value - } - if (colorObj.lumOff && colorObj.lumOff > 0) { - let value = colorObj.lumOff / 100000 - r += 255 * value - g += 255 * value - b += 255 * value - } - } - return `rgba(${r}, ${g}, ${b}, ${a})` -} - -function loadChartImage(src) { - return new Promise(resolve => { - if (!src) { - resolve() - return - } - let img = new Image() - let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) - if (!eqOrigin) { - img.crossOrigin = 'anonymous' - } - img.src = src - img.onload = function() { - resolve(img) - } - img.onerror = function (e) { - resolve() - console.log('图片加载失败: ', src, e) - } - }) -} - -export { drawChart } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js deleted file mode 100644 index 05ea6d0..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/cover.js +++ /dev/null @@ -1,95 +0,0 @@ -import { Ppt2Canvas } from './ppt2canvas.js' - -async function drawPptxFun(pptxObj, idx) { - let canvas = document.createElement('canvas') - let width = pptxObj.width - let height = pptxObj.height - canvas.width = width * 2 - canvas.height = height * 2 - canvas.style.width = width + 'px' - canvas.style.height = height + 'px' - let ctx = canvas.getContext('2d') - ctx.scale(2, 2) - ctx.imageSmoothingEnabled = true - ctx.imageSmoothingQuality = 'high' - let ppt2Canvas = new Ppt2Canvas(canvas, 'anonymous') - await ppt2Canvas.drawPptx(pptxObj, idx) - return ppt2Canvas.getCanvas() -} - -// drawPptxFun = async (pptxObj, idx) => return canvas -async function drawCover(pptxObj, drawPptxFun, grayScale) { - let pages = pptxObj.pages - if (pages.length == 1) { - let _canvas = await drawPptxFun(pptxObj, 0, pptxObj.width, pptxObj.height) - return _canvas.toDataURL() - } - async function drawPptxImage(pptxObj, idx) { - let _canvas = await drawPptxFun(pptxObj, idx) - let imgSrc = _canvas.toDataURL() - return new Promise(resolve => { - let image = new Image() - image.src = imgSrc - image.onload = async function() { - resolve(image) - } - }) - } - // let width = 1200, height = 676 - let width = 600, height = 338 - let canvas = document.createElement('canvas') - canvas.width = width - canvas.height = height - let ctx = canvas.getContext('2d') - ctx.imageSmoothingEnabled = true - ctx.imageSmoothingQuality = 'high' - - ctx.fillStyle = 'rgb(212, 212, 212)' - ctx.fillRect(0, 0, width, height) - - let size = 0 - let w = width / 3.3, h = height / 3.3 - for (let i = 1; i < pages.length; i++) { - size++ - let x = 0 - let y = 0 - if (size == 2 || size == 7) { - x = w + (width - w * 3) / 2 - } else if (size == 3 || size == 5 || size == 8) { - x = width - w - } - if (size == 4 || size == 5) { - y = h + (height - h * 3) / 2 - } else if (size > 5) { - y = height - h - } - let image = await drawPptxImage(pptxObj, i) - ctx.drawImage(image, x, y, w, h) - if (size == 8) { - break - } - } - w = width * 0.65 - h = height * 0.65 - let image = await drawPptxImage(pptxObj, 0) - ctx.drawImage(image, (width - w) / 2, (height - h) / 2, w, h) - ctx.rect((width - w) / 2, (height - h) / 2, w, h) - ctx.lineWidth = 1 - ctx.strokeStyle = 'rgb(212, 212, 212)' - ctx.stroke() - if (grayScale) { - // 灰度 - let imageData = ctx.getImageData(0, 0, width, height) - let data = imageData.data - for (let i = 0; i < data.length; i += 4) { - let luminance = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114 - data[i] = luminance - data[i + 1] = luminance - data[i + 2] = luminance - } - ctx.putImageData(imageData, 0, 0) - } - return canvas.toDataURL() -} - -export { drawPptxFun, drawCover } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js deleted file mode 100644 index 08abc73..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/element.js +++ /dev/null @@ -1,692 +0,0 @@ -// 创建空白页 -function createPage(page, width, height) { - return { - page: page || 1, - extInfo: { - background: { - realType: 'Background', - anchor: [0, 0, width || 960, height || 540], - fillStyle: { - type: 'color', - color: { - color: -1, - realColor: -1 - } - } - }, - slideMasterIdx: 0, - slideLayoutIdx: 0 - }, - children: [] - } -} - -// 创建文本框 -// @param subType 类型 => title1 标题; title2 副标题; content 正文内容 -// @param fontFamily 字体(默认 null) -// @param fontColor 文字颜色(默认 null) -function createTextBox(subType, fontFamily, fontColor) { - const fontSize = (subType == 'title1' ? 70 : (subType == 'title2' ? 35 : 18)) - const text = (subType == 'title1' || subType == 'title2' ? '输入标题' : '请输入内容') - const textWordWrap = (subType == 'title1' || subType == 'title2' ? false : true) - const textAlign = (subType == 'title1' || subType == 'title2' ? 'CENTER' : 'LEFT') - const width = (text.length + 1) * fontSize - const anchor = [(960 - width) / 2, 540 / 2 - fontSize, width, fontSize] - if (textAlign == 'CENTER') { - anchor[0] = (960 - width) / 2 - } else { - anchor[0] = 960 / 2 - width - } - const id = 'txt' + Math.floor((Math.random() * 100000) + 100000) - if (!fontColor && subType == 'title1') { - // 标题默认颜色 - fontColor = { - type: 'gradient', - gradient: { - angle: 90, - colors: [ - {color: -7614, realColor: -7614, alpha: 100000}, - {color: -1838, realColor: -1838, alpha: 100000}, - {color: -7614, realColor: -7614, alpha: 100000}, - {color: -25569, realColor: -25569, alpha: 100000}, - {color: -7614, realColor: -7614, alpha: 100000} - ], - fractions: [0.06, 0.26, 0.5, 0.71, 0.89], - gradientType: 'linear' - } - } - } else if (!fontColor) { - // 正文默认颜色 - fontColor = { - type: 'color', - color: { - scheme: null, - realColor: -16777216, - color: -16777216 - }, - gradient: null - } - } - return { - id: `${id}`, - type: 'text', - depth: 1, - point: [...anchor], - extInfo: { - property: { - realType: 'TextBox', - shapeType: 'rect', - anchor: [...anchor], - fillStyle: { - type: 'noFill' - }, - geometry: { - name: 'rect' - }, - textAutofit: 'SHAPE', - textDirection: 'HORIZONTAL', - textVerticalAlignment: 'TOP', - textWordWrap: textWordWrap, - textInsets: [3.6,7.2,3.6,7.2] - } - }, - children: [ - { - id: `${id}_p`, - pid: `${id}`, - type: 'p', - depth: 2, - extInfo: { - property: { - textAlign: textAlign, - leftMargin: 0 - } - }, - children: [ - { - id: `${id}_p_r`, - pid: `${id}_p`, - type: 'r', - text: text, - depth: 3, - extInfo: { - property: { - fontSize: fontSize, - bold: null, - fontFamily: fontFamily, - fontColor: {...fontColor}, - line: null, - lang: 'zh-CN' - } - } - } - ] - } - ] - } -} - -// 创建形状 -// @param geometryName 形状名称 => geometryMap key -// @param fillStyle 填充 -// @param strokeStylePaint 画笔填充 -function createGeometry(geometryName, fillStyle, strokeStylePaint) { - const width = 200 - const height = 200 - const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] - const id = 'txt' + Math.floor((Math.random() * 100000) + 100000) - if (!fillStyle) { - fillStyle = { - type: 'color', - color: { - scheme: null, - color: -10773547, - realColor: -10773547 - } - } - } - if (!strokeStylePaint) { - strokeStylePaint = { - type: 'color', - color: { - scheme: null, - color: -10773547, - realColor: -14532775, - shade: 15000 - } - } - } - return { - id: `${id}`, - type: 'text', - depth: 1, - point: [...anchor], - extInfo: { - property: { - realType: 'Auto', - shapeType: geometryName, - anchor: [...anchor], - fillStyle: {...fillStyle}, - strokeStyle: { - paint: {...strokeStylePaint}, - lineWidth: 1, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - geometry: { - name: geometryName, - data: null, - avLst: null - }, - textAutofit: 'NORMAL', - textDirection: 'HORIZONTAL', - textVerticalAlignment: 'MIDDLE', - textInsets: [3.6, 7.2, 3.6, 7.2] - } - }, - children: [ - { - id: `${id}_p`, - pid: `${id}`, - type: 'p', - depth: 2, - extInfo: { - property: { - textAlign: 'CENTER', - leftMargin: 0 - } - }, - children: [] - } - ] - } -} - -// 创建图片 -// @param src 图片src (url/base64) -function createImage(src, width, height) { - if (!width) { - width = 200 - } - if (!height) { - height = 200 - } - const extension = src.indexOf('.png') > -1 || src.indexOf('image/png') ? '.png' : '.jpg' - const id = 'img' + Math.floor((Math.random() * 100000) + 100000) - const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] - const contentType = extension == '.png' ? 'image/png' : 'image/jpeg' - return { - id: id, - depth: 1, - type: 'image', - point: [...anchor], - extInfo: { - property: { - image: src, - anchor: [...anchor], - extension: extension, - fileName: 'image' + extension, - contentType: contentType, - fillStyle: { - type: 'texture', - texture: { - imageData: '$image', - flipMode: 'NONE', - insets: [0, 0, 0, 0], - stretch: [0, 0, 0, 0], - contentType: contentType - } - }, - flipHorizontal: false, - flipVertical: false, - realType: 'Picture', - geometry: { - name: 'rect' - } - } - }, - children: [] - } -} - -// 创建表格 -// @param rowColumnDataList 表格数据: [['第1行1列', '第1行2列', '第1行3列'], ['第2行1列', '第2行2列', '第2行3列'], ['第3行1列', '第3行2列', '第3行3列']] -// @param rowFillStyles 填充色(按行循环交替) -// @param borderColor 边框颜色 -// @param fontColor 字体颜色 -function createTable(rowColumnDataList, rowFillStyles, borderColor, fontColor) { - const rowNum = rowColumnDataList.length - const columnNum = rowColumnDataList[0].length - const lineWidth = 1 - const fontSize = 16 - const textAlign = 'LEFT' - const rowHeight = 65, colWidth = 80 - const width = rowHeight * rowNum + lineWidth * (rowNum + 1) - const height = colWidth * columnNum + lineWidth * (columnNum + 1) - const tableAnchor = [(960 - width) / 2, (540 - height) / 2, width, height] - const id = 'tab' + Math.floor((Math.random() * 100000) + 100000) - const rows = [] - if (!rowFillStyles) { - rowFillStyles = [ - { - type: 'color', - color: { - color: -7555288, - realColor: -1378864, - lumMod: 20000, - lumOff: 80000 - } - }, - { - type: 'color', - color: { - color: -7555288, - realColor: -2823519, - lumMod: 40000, - lumOff: 60000 - } - } - ] - } - if (!fontColor) { - fontColor = { - type: 'color', - color: { - color: -16777216, - realColor: -16777216, - alpha: 100000 - } - } - } - if (borderColor == null) { - borderColor = -7555288 - } - for (let i = 0; i < rowNum; i++) { - const columns = [] - const fillStyle = rowFillStyles[i % rowFillStyles.length] - for (let j = 0; j < columnNum; j++) { - let text = rowColumnDataList[i][j] - columns.push({ - id: `${id}_r${i}_c${j}`, - pid: `${id}_r${i}`, - type: 'tableColumn', - depth: 3, - extInfo: { - property: { - realType: 'TableCell', - anchor: [tableAnchor[0] + colWidth * j + lineWidth * (j + 1), tableAnchor[1] + rowHeight * i + lineWidth * (i + 1), colWidth, rowHeight], - fillStyle: {...fillStyle}, - strokeStyle: {}, - geometry: { - name: 'tableColumn' - }, - textAutofit: 'NORMAL', - textDirection: 'HORIZONTAL', - textVerticalAlignment: 'MIDDLE', - textInsets: [3.6, 7.2, 3.6, 7.2], - columnWidth: colWidth, - borders: [ - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - }, - { - color: borderColor, - lineWidth: lineWidth, - lineCap: 'FLAT', - lineDash: 'SOLID', - lineCompound: 'SINGLE' - } - ] - } - }, - children: [ - { - id: `${id}_r${i}_c${j}_p`, - pid: `${id}_r${i}_c${j}`, - type: 'p', - depth: 4, - extInfo: { - property: { - textAlign: textAlign, - leftMargin: 0 - } - }, - children: [ - { - id: `${id}_r${i}_c${j}_p_r`, - pid: `${id}_r${i}_c${j}_p`, - type: 'r', - text: text, - depth: 5, - extInfo: { - property: { - fontSize: fontSize, - fontColor: {...fontColor}, - lang: 'zh-CN' - } - } - } - ] - } - ] - }) - } - rows.push({ - id: `${id}_r${i}`, - pid: `${id}`, - type: 'tableRow', - depth: 2, - extInfo: { - property: { - rowHeight: rowHeight - } - }, - children: columns - }) - } - return { - id: `${id}`, - pid: null, - type: 'table', - text: null, - depth: 1, - point: [...tableAnchor], - extInfo: { - property: { - anchor: [...tableAnchor], - realType: 'table', - numberOfRows: rowNum, - numberOfColumns: columnNum - } - }, - children: rows - } -} - -// 创建图表 -// @param title 图表标题 -// @param chartType 图表类型 pie/doughnut/bar/line -// @param rowColumnDataList 表格数据: -// 柱状图、折线图: [[' ','系列 1','系列 2','系列 3'], ['类别 1','4.3','2.4','2'], ['类别 2','2.5','4.4','2'], ['类别 3','3.5','1.8','3'], ['类别 4','4.5','2.8','5']] -// 饼图、环形图: [[' ','销售额'], ['第一季度','8.2'], ['第二季度','3.2'], ['第三季度','1.4'], ['第四季度','1.2']] -// @param colors 颜色 [{type:'color',color:{realColor:-1213135}}] -function createChart(title, chartType, rowColumnDataList, colors) { - if (!colors) { - colors = [ - {type: 'color', color: { color: -478429, realColor: -478429 }}, - {type: 'color', color: { color: -10130855, realColor: -10130855 }}, - {type: 'color', color: { color: -12143947, realColor: -12143947 }}, - {type: 'color', color: { color: -7558530, realColor: -7558530 }}, - {type: 'color', color: { color: -2920600, realColor: -2920600 }}, - {type: 'color', color: { color: -8232330, realColor: -8232330 }} - ] - } - if (chartType == 'pie' || chartType == 'doughnut') { - rowColumnDataList[0][1] = rowColumnDataList[0][1] || title - return createPieChart(rowColumnDataList, chartType == 'doughnut' ? 50 : 0, colors) - } else if (chartType == 'bar' || chartType == 'line') { - return createBarLineChart(title, chartType, rowColumnDataList, colors) - } - return null -} - -function createPieChart(rowColumnDataList, holeSize, colors) { - const width = 400 - const height = 220 - const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] - const id = 'chart' + Math.floor((Math.random() * 100000) + 100000) - const dataPoint = [] - for (let i = 1; i < rowColumnDataList.length; i++) { - dataPoint.push({ - property: { - anchor: null, - fillStyle: colors[(i - 1) % colors.length], - strokeStyle: { - paint: { - type: 'color', - color: { - scheme: 'lt1', - realColor: -1, - color: -1 - } - }, - lineWidth: 1.5 - }, - geometry: null, - shadow: null - } - }) - } - const chartData = { - chartType: holeSize ? 'doughnut' : 'pie', - series: [ - { - text: { - formula: 'Sheet1!$B$1', - formatCode: null, - data: [rowColumnDataList[0][1]] - }, - category: { - formula: 'Sheet1!$A$2:$A$' + rowColumnDataList.length, - formatCode: null, - data: rowColumnDataList.map(s => s[0]).splice(1) - }, - value: { - formula: 'Sheet1!$B$2:$B$' + rowColumnDataList.length, - formatCode: 'General', - data: rowColumnDataList.map(s => s[1]).splice(1) - }, - dataPoint: dataPoint, - property: null - } - ], - categoryAxis: null, - valueAxes: null, - extInfo: holeSize ? { holeSize: holeSize } : {} - } - return { - id: id, - type: 'graphicFrame', - depth: 1, - point: [...anchor], - extInfo: { - property: { - anchor: [...anchor], - chart: { - title: '', - legend: { - position: 'BOTTOM', - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - }, - excelData: [ - { - sheetName: 'Sheet1', - rows: rowColumnDataList - } - ], - chartData: [chartData] - }, - realType: 'graphicFrame' - } - }, - children: [] - } -} - -function createBarLineChart(title, chartType, rowColumnDataList, colors) { - const width = 460 - const height = 270 - const anchor = [(960 - width) / 2, (540 - height) / 2, width, height] - const id = 'chart' + Math.floor((Math.random() * 100000) + 100000) - const series = [] - for (let i = 1; i < rowColumnDataList[0].length; i++) { - const vf = String.fromCharCode(65 + i) - series.push({ - text: { - formula: 'Sheet1!$' + vf + '$1', - formatCode: null, - data: [rowColumnDataList[0][i]] - }, - category: { - formula: 'Sheet1!$A$' + (i + 1) + ':$A$' + rowColumnDataList.length, - formatCode: null, - data: rowColumnDataList.map(s => s[0]).splice(1) - }, - value: { - formula: 'Sheet1!$' + vf + '$' + (i + 1) + ':$' + vf + '$' + rowColumnDataList.length, - formatCode: 'General', - data: rowColumnDataList.map(s => s[i]).splice(1) - }, - dataPoint: [null], - property: { - anchor: null, - fillStyle: chartType == 'line' ? null : colors[(i - 1) % colors.length], - strokeStyle: chartType == 'line' ? { - paint: colors[(i - 1) % colors.length], - lineWidth: 2.25, - lineCap: 'ROUND' - } : { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - }) - } - let extInfo = {} - if (chartType == 'bar') { - extInfo = { - type: 'col', - overlap: '-27', - gapWidth: '219', - majorGridlines: 'true' - } - } else if (chartType == 'line') { - extInfo = { majorGridlines: 'true' } - } - return { - id: id, - type: 'graphicFrame', - depth: 1, - point: [...anchor], - extInfo: { - property: { - anchor: [...anchor], - chart: { - title: title, - legend: { - position: 'BOTTOM', - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - }, - excelData: [ - { - sheetName: 'Sheet1', - rows: rowColumnDataList - } - ], - chartData: [ - { - chartType: chartType, - series: series, - categoryAxis: { - position: 'BOTTOM', - deleted: false, - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'color', - color: { - realColor: -2500135, - color: -16777216, - lumMod: 15000, - lumOff: 85000 - } - }, - lineWidth: 0.75, - lineCap: 'FLAT', - lineCompound: 'SINGLE' - }, - geometry: null, - shadow: null - } - }, - valueAxes: [ - { - position: 'LEFT', - deleted: false, - property: { - anchor: null, - fillStyle: { - type: 'noFill' - }, - strokeStyle: { - paint: { - type: 'noFill' - } - }, - geometry: null, - shadow: null - } - } - ], - extInfo: extInfo - } - ] - }, - realType: 'graphicFrame' - } - }, - children: [] - } -} - -export { createPage, createTextBox, createGeometry, createImage, createTable, createChart } diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js deleted file mode 100644 index 1d67490..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/geometry.js +++ /dev/null @@ -1,500 +0,0 @@ -/* eslint-disable no-fallthrough */ -/* eslint-disable no-case-declarations */ -const geometryMap = {"curvedDownArrow":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 100000","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","wR:+- wd2 0 q1","q7:*/ wR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idy:*/ q11 h q7","maxAdj3:*/ 100000 idy ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss adj3 100000","x3:+- wR th 0","q2:*/ h h 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dx:*/ q5 wR h","x5:+- wR dx 0","x7:+- x3 dx 0","q6:+- aw 0 th","dh:*/ q6 1 2","x4:+- x5 0 dh","x8:+- x7 dh 0","aw2:*/ aw 1 2","x6:+- r 0 aw2","y1:+- b 0 ah","swAng:at2 ah dx","mswAng:+- 0 0 swAng","iy:+- b 0 idy","ix:+/ wR x3 2","q12:*/ th 1 2","dang2:at2 idy q12","stAng:+- 3cd4 swAng 0","stAng2:+- 3cd4 0 dang2","swAng2:+- dang2 0 cd4","swAng3:+- cd4 dang2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x6 b L x4 y1 L x5 y1 A wR h stAng mswAng L x3 t A wR h 3cd4 swAng L x8 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L l b A wR h cd2 swAng3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L l b A wR h cd2 cd4 L x3 t A wR h 3cd4 swAng L x8 y1 L x6 b L x4 y1 L x5 y1 A wR h stAng mswAng","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"quadArrowCallout":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:+- 50000 0 a2","a3:pin 0 adj3 maxAdj3","q2:*/ a3 2 1","maxAdj4:+- 100000 0 q2","a4:pin a1 adj4 maxAdj4","dx2:*/ ss a2 100000","dx3:*/ ss a1 200000","ah:*/ ss a3 100000","dx1:*/ w a4 200000","dy1:*/ h a4 200000","x8:+- r 0 ah","x2:+- hc 0 dx1","x7:+- hc dx1 0","x3:+- hc 0 dx2","x6:+- hc dx2 0","x4:+- hc 0 dx3","x5:+- hc dx3 0","y8:+- b 0 ah","y2:+- vc 0 dy1","y7:+- vc dy1 0","y3:+- vc 0 dx2","y6:+- vc dx2 0","y4:+- vc 0 dx3","y5:+- vc dx3 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L ah y3 L ah y4 L x2 y4 L x2 y2 L x4 y2 L x4 ah L x3 ah L hc t L x6 ah L x5 ah L x5 y2 L x7 y2 L x7 y4 L x8 y4 L x8 y3 L r vc L x8 y6 L x8 y5 L x7 y5 L x7 y7 L x5 y7 L x5 y8 L x6 y8 L hc b L x3 y8 L x4 y8 L x4 y7 L x2 y7 L x2 y5 L ah y5 L ah y6 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18515","adj2:val 18515","adj3:val 18515","adj4:val 48123"]},"funnel":{"guides":["d:*/ ss 1 20","rw2:+- wd2 0 d","rh2:+- hd4 0 d","t1:cos wd2 480000","t2:sin hd4 480000","da:at2 t1 t2","2da:*/ da 2 1","stAng1:+- cd2 0 da","swAng1:+- cd2 2da 0","swAng3:+- cd2 0 2da","rw3:*/ wd2 1 4","rh3:*/ hd4 1 4","ct1:cos hd4 stAng1","st1:sin wd2 stAng1","m1:mod ct1 st1 0","n1:*/ wd2 hd4 m1","dx1:cos n1 stAng1","dy1:sin n1 stAng1","x1:+- hc dx1 0","y1:+- hd4 dy1 0","ct3:cos rh3 da","st3:sin rw3 da","m3:mod ct3 st3 0","n3:*/ rw3 rh3 m3","dx3:cos n3 da","dy3:sin n3 da","x3:+- hc dx3 0","vc3:+- b 0 rh3","y2:+- vc3 dy3 0","x2:+- wd2 0 rw2","cd:*/ cd2 2 1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd4 stAng1 swAng1 L x3 y2 A rw3 rh3 da swAng3 Z M x2 hd4 A rw2 rh2 cd2 -21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"doubleWave":{"guides":["a1:pin 0 adj1 12500","a2:pin -10000 adj2 10000","y1:*/ h a1 100000","dy2:*/ y1 10 3","y2:+- y1 0 dy2","y3:+- y1 dy2 0","y4:+- b 0 y1","y5:+- y4 0 dy2","y6:+- y4 dy2 0","dx1:*/ w a2 100000","of2:*/ w a2 50000","x1:abs dx1","dx2:?: of2 0 of2","x2:+- l 0 dx2","dx8:?: of2 of2 0","x8:+- r 0 dx8","dx3:+/ dx2 x8 6","x3:+- x2 dx3 0","dx4:+/ dx2 x8 3","x4:+- x2 dx4 0","x5:+/ x2 x8 2","x6:+- x5 dx3 0","x7:+/ x6 x8 2","x9:+- l dx8 0","x15:+- r dx2 0","x10:+- x9 dx3 0","x11:+- x9 dx4 0","x12:+/ x9 x15 2","x13:+- x12 dx3 0","x14:+/ x13 x15 2","x16:+- r 0 x1","xAdj:+- hc dx1 0","il:max x2 x9","ir:min x8 x15","it:*/ h a1 50000","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 y1 C x3 y2 x4 y3 x5 y1 C x6 y2 x7 y3 x8 y1 L x15 y4 C x14 y6 x13 y5 x12 y4 C x11 y6 x10 y5 x9 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 6250","adj2:val 0"]},"parallelogram":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 200000","x2:*/ ss a 100000","x6:+- r 0 x1","x5:+- r 0 x2","x3:*/ x5 1 2","x4:+- r 0 x3","il:*/ wd2 a maxAdj","q1:*/ 5 a maxAdj","q2:+/ 1 q1 12","il:*/ q2 w 1","it:*/ q2 h 1","ir:+- r 0 il","ib:+- b 0 it","q3:*/ h hc x2","y1:pin 0 q3 h","y2:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L r t L x5 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"rightArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss w","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","dx3:*/ ss a3 100000","x3:+- r 0 dx3","x2:*/ w a4 100000","x1:*/ x2 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x2 t L x2 y2 L x3 y2 L x3 y1 L r vc L x3 y4 L x3 y3 L x2 y3 L x2 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"actionButtonForwardNext":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g12 vc L g11 g9 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g12 vc L g11 g9 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g12 vc L g11 g10 L g11 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartDisplay":{"guides":["x2:*/ w 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 0 3 L 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"plaqueTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t A dx dx 0 cd4 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 A dx dx 3cd4 cd4 L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r t L r dx A dx dx cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 b A dx dx cd2 cd4 L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonInformation":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g11:+- hc 0 dx2","g13:*/ ss 3 4","g14:*/ g13 1 32","g17:*/ g13 5 16","g18:*/ g13 3 8","g19:*/ g13 13 32","g20:*/ g13 19 32","g22:*/ g13 11 16","g23:*/ g13 13 16","g24:*/ g13 7 8","g25:+- g9 g14 0","g28:+- g9 g17 0","g29:+- g9 g18 0","g30:+- g9 g23 0","g31:+- g9 g24 0","g32:+- g11 g17 0","g34:+- g11 g19 0","g35:+- g11 g20 0","g37:+- g11 g22 0","g38:*/ g13 3 32"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M hc g9 A dx2 dx2 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M hc g9 A dx2 dx2 3cd4 21600000 Z M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g32 g29 L g34 g29 L g34 g30 L g32 g30 L g32 g31 L g37 g31 L g37 g30 L g35 g30 L g35 g28 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g35 g28 L g35 g30 L g37 g30 L g37 g31 L g32 g31 L g32 g30 L g34 g30 L g34 g29 L g32 g29 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc g9 A dx2 dx2 3cd4 21600000 Z M hc g25 A g38 g38 3cd4 21600000 M g32 g28 L g35 g28 L g35 g30 L g37 g30 L g37 g31 L g32 g31 L g32 g30 L g34 g30 L g34 g29 L g32 g29 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartOfflineStorage":{"guides":["x4:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":false,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":5,"path":"M 2 4 L 3 4","stroked":true,"w":5,"windingRule":1},{"extrusionOk":true,"fill":"NONE","filled":false,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"upArrow":{"guides":["maxAdj2:*/ 100000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dy2:*/ ss a2 100000","y2:+- t dy2 0","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:*/ x1 dy2 wd2","y1:+- y2 0 dy1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L hc t L r y2 L x2 y2 L x2 b L x1 b L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"chartStar":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 0 0 L 10 10 M 0 10 L 10 0 M 5 0 L 5 10","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"actionButtonBlank":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"corner":{"guides":["maxAdj1:*/ 100000 h ss","maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 maxAdj1","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","dy1:*/ ss a1 100000","y1:+- b 0 dy1","cx1:*/ x1 1 2","cy1:+/ y1 b 2","d:+- w 0 h","it:?: d y1 t","ir:?: d r x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L x1 y1 L r y1 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"cloudCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","ht:cat2 hd2 dxPos dyPos","wt:sat2 wd2 dxPos dyPos","g2:cat2 wd2 ht wt","g3:sat2 hd2 ht wt","g4:+- hc g2 0","g5:+- vc g3 0","g6:+- g4 0 xPos","g7:+- g5 0 yPos","g8:mod g6 g7 0","g9:*/ ss 6600 21600","g10:+- g8 0 g9","g11:*/ g10 1 3","g12:*/ ss 1800 21600","g13:+- g11 g12 0","g14:*/ g13 g6 g8","g15:*/ g13 g7 g8","g16:+- g14 xPos 0","g17:+- g15 yPos 0","g18:*/ ss 4800 21600","g19:*/ g11 2 1","g20:+- g18 g19 0","g21:*/ g20 g6 g8","g22:*/ g20 g7 g8","g23:+- g21 xPos 0","g24:+- g22 yPos 0","g25:*/ ss 1200 21600","g26:*/ ss 600 21600","x23:+- xPos g26 0","x24:+- g16 g25 0","x25:+- g23 g12 0","il:*/ w 2977 21600","it:*/ h 3262 21600","ir:*/ w 17087 21600","ib:*/ h 17337 21600","g27:*/ w 67 21600","g28:*/ h 21577 21600","g29:*/ w 21582 21600","g30:*/ h 1235 21600","pang:at2 dxPos dyPos"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":43200,"path":"M 3900 14370 A 6753 9190 -11429249 7426832 A 5333 7267 -8646143 5396714 A 4365 5945 -8748475 5983381 A 4857 6595 -7859164 7034504 A 5333 7273 -4722533 6541615 A 6775 9220 -2776035 7816140 A 5785 7867 37501 6842000 A 6752 9215 1347096 6910353 A 7720 10543 3974558 4542661 A 4360 5918 -16496525 8804134 A 4345 5945 -14809710 9151131 Z","stroked":true,"w":43200,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x23 yPos A g26 g26 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x24 g17 A g25 g25 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x25 g24 A g12 g12 0 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":43200,"path":"M 4693 26177 A 4345 5945 5204520 1585770 M 6928 34899 A 4360 5918 4416628 686848 M 16478 39090 A 6752 9215 8257449 844866 M 28827 34751 A 6752 9215 387196 959901 M 34129 22954 A 5785 7867 -4217541 4255042 M 41798 15354 A 5333 7273 1819082 1665090 M 38324 5426 A 4857 6595 -824660 891534 M 29078 3952 A 4857 6595 -8950887 1091722 M 22141 4720 A 4365 5945 -9809656 1061181 M 14000 5192 A 6753 9190 -4002417 739161 M 4127 15789 A 6753 9190 9459261 711490","stroked":true,"w":43200,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"horizontalScroll":{"guides":["a:pin 0 adj 25000","ch:*/ ss a 100000","ch2:*/ ch 1 2","ch4:*/ ch 1 4","y3:+- ch ch2 0","y4:+- ch ch 0","y6:+- b 0 ch","y7:+- b 0 ch2","y5:+- y6 0 ch2","x3:+- r 0 ch","x4:+- r 0 ch2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r ch2 A ch2 ch2 0 cd4 L x4 ch2 A ch4 ch4 0 cd2 L x3 ch L ch2 ch A ch2 ch2 3cd4 -5400000 L l y7 A ch2 ch2 cd2 -10800000 L ch y6 L x4 y6 A ch2 ch2 cd4 -5400000 Z M ch2 y4 A ch2 ch2 cd4 -5400000 A ch4 ch4 0 -10800000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M ch2 y4 A ch2 ch2 cd4 -5400000 A ch4 ch4 0 -10800000 Z M x4 ch A ch2 ch2 cd4 -16200000 A ch4 ch4 cd2 -10800000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l y3 A ch2 ch2 cd2 cd4 L x3 ch L x3 ch2 A ch2 ch2 cd2 cd2 L r y5 A ch2 ch2 0 cd4 L ch y6 L ch y7 A ch2 ch2 0 cd2 Z M x3 ch L x4 ch A ch2 ch2 cd4 -5400000 M x4 ch L x4 ch2 A ch4 ch4 0 cd2 M ch2 y4 L ch2 y3 A ch4 ch4 cd2 cd2 A ch2 ch2 0 cd2 M ch y3 L ch y6","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"cube":{"guides":["a:pin 0 adj 100000","y1:*/ ss a 100000","y4:+- b 0 y1","y2:*/ y4 1 2","y3:+/ y1 b 2","x4:+- r 0 y1","x2:*/ x4 1 2","x3:+/ y1 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x4 y1 L x4 b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x4 y1 L r t L r y4 L x4 b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN_LESS","filled":true,"h":-1,"path":"M l y1 L y1 t L r t L x4 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l y1 L y1 t L r t L r y4 L x4 b L l b Z M l y1 L x4 y1 L r t M x4 y1 L x4 b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"homePlate":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","dx1:*/ ss a 100000","x1:+- r 0 dx1","ir:+/ x1 r 2","x2:*/ x1 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L r vc L x1 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"pentagon":{"guides":["swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:cos swd2 1080000","dx2:cos swd2 18360000","dy1:sin shd2 1080000","dy2:sin shd2 18360000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc 0 dy2","it:*/ y1 dx2 dx1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L hc t L x4 y1 L x3 y2 L x2 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["hf:val 105146","vf:val 110557"]},"verticalScroll":{"guides":["a:pin 0 adj 25000","ch:*/ ss a 100000","ch2:*/ ch 1 2","ch4:*/ ch 1 4","x3:+- ch ch2 0","x4:+- ch ch 0","x6:+- r 0 ch","x7:+- r 0 ch2","x5:+- x6 0 ch2","y3:+- b 0 ch","y4:+- b 0 ch2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M ch2 b A ch2 ch2 cd4 -5400000 L ch2 y4 A ch4 ch4 cd4 -10800000 L ch y3 L ch ch2 A ch2 ch2 cd2 cd4 L x7 t A ch2 ch2 3cd4 cd2 L x6 ch L x6 y4 A ch2 ch2 0 cd4 Z M x4 ch2 A ch2 ch2 0 cd4 A ch4 ch4 cd4 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x4 ch2 A ch2 ch2 0 cd4 A ch4 ch4 cd4 cd2 Z M ch y4 A ch2 ch2 0 3cd4 A ch4 ch4 3cd4 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ch y3 L ch ch2 A ch2 ch2 cd2 cd4 L x7 t A ch2 ch2 3cd4 cd2 L x6 ch L x6 y4 A ch2 ch2 0 cd4 L ch2 b A ch2 ch2 cd4 cd2 Z M x3 t A ch2 ch2 3cd4 cd2 A ch4 ch4 cd4 cd2 L x4 ch2 M x6 ch L x3 ch M ch2 y3 A ch4 ch4 3cd4 cd2 L ch y4 M ch2 b A ch2 ch2 cd4 -5400000 L ch y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"roundRect":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd2 cd4 L x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4 L x1 b A x1 x1 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"stripedRightArrow":{"guides":["maxAdj2:*/ 84375 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","x4:*/ ss 5 32","dx5:*/ ss a2 100000","x5:+- r 0 dx5","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx6:*/ dy1 dx5 hd2","x6:+- r 0 dx6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L ssd32 y1 L ssd32 y2 L l y2 Z M ssd16 y1 L ssd8 y1 L ssd8 y2 L ssd16 y2 Z M x4 y1 L x5 y1 L x5 t L r vc L x5 b L x5 y2 L x4 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartSort":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":false,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":2,"path":"M 0 1 L 2 1","stroked":true,"w":2,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"mathPlus":{"guides":["a1:pin 0 adj1 73490","dx1:*/ w 73490 200000","dy1:*/ h 73490 200000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dx2","y3:+- vc dx2 0","y4:+- vc dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L x2 y2 L x2 y1 L x3 y1 L x3 y2 L x4 y2 L x4 y3 L x3 y3 L x3 y4 L x2 y4 L x2 y3 L x1 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"swooshArrow":{"guides":["a1:pin 1 adj1 75000","maxAdj2:*/ 70000 w ss","a2:pin 0 adj2 maxAdj2","ad1:*/ h a1 100000","ad2:*/ ss a2 100000","xB:+- r 0 ad2","yB:+- t ssd8 0","alfa:*/ cd4 1 14","dx0:tan ssd8 alfa","xC:+- xB 0 dx0","dx1:tan ad1 alfa","yF:+- yB ad1 0","xF:+- xB dx1 0","xE:+- xF dx0 0","yE:+- yF ssd8 0","dy2:+- yE 0 t","dy22:*/ dy2 1 2","dy3:*/ h 1 20","yD:+- t dy22 dy3","dy4:*/ hd6 1 1","yP1:+- hd6 dy4 0","xP1:val wd6","dy5:*/ hd6 1 2","yP2:+- yF dy5 0","xP2:val wd4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b Q xP1 yP1 xB yB L xC t L r yD L xE yE L xF yF Q xP2 yP2 l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 16667"]},"wedgeRectCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","dx:+- xPos 0 hc","dy:+- yPos 0 vc","dq:*/ dxPos h w","ady:abs dyPos","adq:abs dq","dz:+- ady 0 adq","xg1:?: dxPos 7 2","xg2:?: dxPos 10 5","x1:*/ w xg1 12","x2:*/ w xg2 12","yg1:?: dyPos 7 2","yg2:?: dyPos 10 5","y1:*/ h yg1 12","y2:*/ h yg2 12","t1:?: dxPos l xPos","xl:?: dz l t1","t2:?: dyPos x1 xPos","xt:?: dz t2 x1","t3:?: dxPos xPos r","xr:?: dz r t3","t4:?: dyPos xPos x1","xb:?: dz t4 x1","t5:?: dxPos y1 yPos","yl:?: dz y1 t5","t6:?: dyPos t yPos","yt:?: dz t6 t","t7:?: dxPos yPos y1","yr:?: dz y1 t7","t8:?: dyPos yPos b","yb:?: dz t8 b"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L xt yt L x2 t L r t L r y1 L xr yr L r y2 L r b L x2 b L xb yb L x1 b L l b L l y2 L xl yl L l y1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"circularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","maxAng:abs u21","aAng:pin 0 adj2 maxAng","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","wtE:sin rw1 stAng","htE:cos rh1 stAng","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng:?: ist0 ist0 ist1","isw1:+- stAng 0 istAng","isw2:+- isw1 0 21600000","iswAng:?: isw1 isw2 isw1","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","sw0:+- en2 0 stAng","sw1:+- sw0 21600000 0","swAng:?: sw0 sw0 sw1","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","aI:+- stAng 0 cd4","aA:+- ptAng cd4 0","aB:+- ptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xE yE A rw1 rh1 stAng swAng L xGp yGp L xA yA L xBp yBp L xC yC A rw2 rh2 istAng iswAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 1142319","adj3:val 20457681","adj4:val 10800000","adj5:val 12500"]},"moon":{"guides":["a:pin 0 adj 87500","g0:*/ ss a 100000","g0w:*/ g0 w ss","g1:+- ss 0 g0","g2:*/ g0 g0 g1","g3:*/ ss ss g1","g4:*/ g3 2 1","g5:+- g4 0 g2","g6:+- g5 0 g0","g6w:*/ g6 w ss","g7:*/ g5 1 2","g8:+- g7 0 g0","dy1:*/ g8 hd2 ss","g10h:+- vc 0 dy1","g11h:+- vc dy1 0","g12:*/ g0 9598 32768","g12w:*/ g12 w ss","g13:+- ss 0 g12","q1:*/ ss ss 1","q2:*/ g13 g13 1","q3:+- q1 0 q2","q4:sqrt q3","dy4:*/ q4 hd2 ss","g15h:+- vc 0 dy4","g16h:+- vc dy4 0","g17w:+- g6w 0 g0w","g18w:*/ g17w 1 2","dx2p:+- g0w g18w w","dx2:*/ dx2p -1 1","dy2:*/ hd2 -1 1","stAng1:at2 dx2 dy2","enAngp1:at2 dx2 hd2","enAng1:+- enAngp1 0 21600000","swAng1:+- enAng1 0 stAng1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A w hd2 cd4 cd2 A g18w dy1 stAng1 swAng1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"leftRightCircularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","maxAng:abs u21","aAng:pin 0 adj2 maxAng","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","lptAng:+- stAng 0 aAng","wtL:sin rw3 lptAng","htL:cos rh3 lptAng","dxL:cat2 rw3 htL wtL","dyL:sat2 rh3 htL wtL","xL:+- hc dxL 0","yL:+- vc dyL 0","dxK:cos thh lptAng","dyK:sin thh lptAng","xK:+- xI dxK 0","yK:+- yI dyK 0","dxJ:cos thh lptAng","dyJ:sin thh lptAng","xJ:+- xI 0 dxJ 0","yJ:+- yI 0 dyJ 0","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","od0:+- en2 0 enAng","od1:+- od0 21600000 0","od2:?: od0 od0 od1","st0:+- stAng 0 od2","st1:+- st0 21600000 0","st2:?: st0 st0 st1","sw0:+- en2 0 st2","sw1:+- sw0 21600000 0","swAng:?: sw0 sw0 sw1","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng:?: ist0 ist0 ist1","id0:+- istAng 0 enAng","id1:+- id0 0 21600000","id2:?: id0 id1 id0","ien0:+- stAng 0 id2","ien1:+- ien0 0 21600000","ien2:?: ien1 ien1 ien0","isw1:+- ien2 0 istAng","isw2:+- isw1 0 21600000","iswAng:?: isw1 isw2 isw1","wtE:sin rw1 st2","htE:cos rh1 st2","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","wtD:sin rw2 ien2","htD:cos rh2 ien2","dxD:cat2 rw2 htD wtD","dyD:sat2 rh2 htD wtD","xD:+- hc dxD 0","yD:+- vc dyD 0","xKp:?: p5 xE xK","yKp:?: p5 yE yK","xJp:?: p5 xD xJ","yJp:?: p5 yD yJ","aL:+- lptAng 0 cd4","aA:+- ptAng cd4 0","aB:+- ptAng cd2 0","aJ:+- lptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xL yL L xKp yKp L xE yE A rw1 rh1 st2 swAng L xGp yGp L xA yA L xBp yBp L xC yC A rw2 rh2 istAng iswAng L xJp yJp Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 1142319","adj3:val 20457681","adj4:val 11942319","adj5:val 12500"]},"uturnArrow":{"guides":["a2:pin 0 adj2 25000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q2:*/ a1 ss h","q3:+- 100000 0 q2","maxAdj3:*/ q3 h ss","a3:pin 0 adj3 maxAdj3","q1:+- a3 a1 0","minAdj5:*/ q1 ss h","a5:pin minAdj5 adj5 100000","th:*/ ss a1 100000","aw2:*/ ss a2 100000","th2:*/ th 1 2","dh2:+- aw2 0 th2","y5:*/ h a5 100000","ah:*/ ss a3 100000","y4:+- y5 0 ah","x9:+- r 0 dh2","bw:*/ x9 1 2","bs:min bw y4","maxAdj4:*/ bs 100000 ss","a4:pin 0 adj4 maxAdj4","bd:*/ ss a4 100000","bd3:+- bd 0 th","bd2:max bd3 0","x3:+- th bd2 0","x8:+- r 0 aw2","x6:+- x8 0 aw2","x7:+- x6 dh2 0","x4:+- x9 0 bd","x5:+- x7 0 bd2","cx:+/ th x7 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l bd A bd bd cd2 cd4 L x4 t A bd bd 3cd4 cd4 L x9 y4 L r y4 L x8 y5 L x6 y4 L x7 y4 L x7 x3 A bd2 bd2 0 -5400000 L x3 th A bd2 bd2 3cd4 -5400000 L th b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 43750","adj5:val 75000"]},"heptagon":{"guides":["swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:*/ swd2 97493 100000","dx2:*/ swd2 78183 100000","dx3:*/ swd2 43388 100000","dy1:*/ shd2 62349 100000","dy2:*/ shd2 22252 100000","dy3:*/ shd2 90097 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc dy2 0","y3:+- svc dy3 0","ib:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L x2 y1 L hc t L x5 y1 L x6 y2 L x4 y3 L x3 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["hf:val 102572","vf:val 105210"]},"star16":{"guides":["a:pin 0 adj 50000","dx1:*/ wd2 92388 100000","dx2:*/ wd2 70711 100000","dx3:*/ wd2 38268 100000","dy1:*/ hd2 92388 100000","dy2:*/ hd2 70711 100000","dy3:*/ hd2 38268 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc dy3 0","y5:+- vc dy2 0","y6:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 98079 100000","sdx2:*/ iwd2 83147 100000","sdx3:*/ iwd2 55557 100000","sdx4:*/ iwd2 19509 100000","sdy1:*/ ihd2 98079 100000","sdy2:*/ ihd2 83147 100000","sdy3:*/ ihd2 55557 100000","sdy4:*/ ihd2 19509 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc sdx4 0","sx6:+- hc sdx3 0","sx7:+- hc sdx2 0","sx8:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc sdy4 0","sy6:+- vc sdy3 0","sy7:+- vc sdy2 0","sy8:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy4 L x1 y3 L sx2 sy3 L x2 y2 L sx3 sy2 L x3 y1 L sx4 sy1 L hc t L sx5 sy1 L x4 y1 L sx6 sy2 L x5 y2 L sx7 sy3 L x6 y3 L sx8 sy4 L r vc L sx8 sy5 L x6 y4 L sx7 sy6 L x5 y5 L sx6 sy7 L x4 y6 L sx5 sy8 L hc b L sx4 sy8 L x3 y6 L sx3 sy7 L x2 y5 L sx2 sy6 L x1 y4 L sx1 sy5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"accentCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"curvedRightArrow":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 a2","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","hR:+- hd2 0 q1","q7:*/ hR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idx:*/ q11 w q7","maxAdj3:*/ 100000 idx ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss a3 100000","y3:+- hR th 0","q2:*/ w w 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dy:*/ q5 hR w","y5:+- hR dy 0","y7:+- y3 dy 0","q6:+- aw 0 th","dh:*/ q6 1 2","y4:+- y5 0 dh","y8:+- y7 dh 0","aw2:*/ aw 1 2","y6:+- b 0 aw2","x1:+- r 0 ah","swAng:at2 ah dy","stAng:+- cd2 0 swAng","mswAng:+- 0 0 swAng","ix:+- r 0 idx","iy:+/ hR y3 2","q12:*/ th 1 2","dang2:at2 idx q12","swAng2:+- dang2 0 cd4","swAng3:+- cd4 dang2 0","stAng3:+- cd2 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l hR A w hR cd2 mswAng L x1 y4 L r y6 L x1 y8 L x1 y7 A w hR stAng swAng Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M r th A w hR 3cd4 swAng2 A w hR stAng3 swAng3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l hR A w hR cd2 mswAng L x1 y4 L r y6 L x1 y8 L x1 y7 A w hR stAng swAng L l hR A w hR cd2 cd4 L r th A w hR 3cd4 swAng2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"accentCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"actionButtonBackPrevious":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 vc L g12 g9 L g12 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 vc L g12 g9 L g12 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 vc L g12 g9 L g12 g10 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonReturn":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 7 8","g15:*/ g13 3 4","g16:*/ g13 5 8","g17:*/ g13 3 8","g18:*/ g13 1 4","g19:+- g9 g15 0","g20:+- g9 g16 0","g21:+- g9 g18 0","g22:+- g11 g14 0","g23:+- g11 g15 0","g24:+- g11 g16 0","g25:+- g11 g17 0","g26:+- g11 g18 0","g27:*/ g13 1 8"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g12 g21 L g23 g9 L hc g21 L g24 g21 L g24 g20 A g27 g27 0 cd4 L g25 g19 A g27 g27 cd4 cd4 L g26 g21 L g11 g21 L g11 g20 A g17 g17 cd2 -5400000 L hc g10 A g17 g17 cd4 -5400000 L g22 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g12 g21 L g23 g9 L hc g21 L g24 g21 L g24 g20 A g27 g27 0 cd4 L g25 g19 A g27 g27 cd4 cd4 L g26 g21 L g11 g21 L g11 g20 A g17 g17 cd2 -5400000 L hc g10 A g17 g17 cd4 -5400000 L g22 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g12 g21 L g22 g21 L g22 g20 A g17 g17 0 cd4 L g25 g10 A g17 g17 cd4 cd4 L g11 g21 L g26 g21 L g26 g20 A g27 g27 cd2 -5400000 L hc g19 A g27 g27 cd4 -5400000 L g24 g21 L hc g21 L g23 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftUpArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:+- 100000 0 maxAdj1","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 50000","x2:+- r 0 dx2","y2:+- b 0 dx2","dx4:*/ ss a2 100000","x4:+- r 0 dx4","y4:+- b 0 dx4","dx3:*/ ss a1 200000","x3:+- x4 0 dx3","x5:+- x4 dx3 0","y3:+- y4 0 dx3","y5:+- y4 dx3 0","il:*/ dx3 x1 dx4","cx1:+/ x1 x5 2","cy1:+/ x1 y5 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y4 L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L x4 t L r x1 L x5 x1 L x5 y5 L x1 y5 L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"star10":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","dx1:*/ swd2 95106 100000","dx2:*/ swd2 58779 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy1:*/ hd2 80902 100000","dy2:*/ hd2 30902 100000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","iwd2:*/ swd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 80902 100000","sdx2:*/ iwd2 30902 100000","sdy1:*/ ihd2 95106 100000","sdy2:*/ ihd2 58779 100000","sx1:+- hc 0 iwd2","sx2:+- hc 0 sdx1","sx3:+- hc 0 sdx2","sx4:+- hc sdx2 0","sx5:+- hc sdx1 0","sx6:+- hc iwd2 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc sdy2 0","sy4:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L sx2 sy2 L x2 y1 L sx3 sy1 L hc t L sx4 sy1 L x3 y1 L sx5 sy2 L x4 y2 L sx6 vc L x4 y3 L sx5 sy3 L x3 y4 L sx4 sy4 L hc b L sx3 sy4 L x2 y4 L sx2 sy3 L x1 y3 L sx1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 42533","hf:val 105146"]},"accentCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"star12":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 1800000","dy1:sin hd2 3600000","x1:+- hc 0 dx1","x3:*/ w 3 4","x4:+- hc dx1 0","y1:+- vc 0 dy1","y3:*/ h 3 4","y4:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:cos iwd2 900000","sdx2:cos iwd2 2700000","sdx3:cos iwd2 4500000","sdy1:sin ihd2 4500000","sdy2:sin ihd2 2700000","sdy3:sin ihd2 900000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc sdx3 0","sx5:+- hc sdx2 0","sx6:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc sdy3 0","sy5:+- vc sdy2 0","sy6:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy3 L x1 hd4 L sx2 sy2 L wd4 y1 L sx3 sy1 L hc t L sx4 sy1 L x3 y1 L sx5 sy2 L x4 hd4 L sx6 sy3 L r vc L sx6 sy4 L x4 y3 L sx5 sy5 L x3 y4 L sx4 sy6 L hc b L sx3 sy6 L wd4 y4 L sx2 sy5 L x1 y3 L sx1 sy4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"flowChartManualOperation":{"guides":["x3:*/ w 4 5","x4:*/ w 9 10"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 0 L 5 0 L 4 5 L 1 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartManualInput":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 1 L 5 0 L 5 5 L 0 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartPunchedCard":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 1 L 1 0 L 5 0 L 5 5 L 0 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"flowChartMultidocument":{"guides":["y2:*/ h 3675 21600","y8:*/ h 20782 21600","x3:*/ w 9298 21600","x4:*/ w 12286 21600","x5:*/ w 18595 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 0 20782 C 9298 23542 9298 18022 18595 18022 L 18595 3675 L 0 3675 Z M 1532 3675 L 1532 1815 L 20000 1815 L 20000 16252 C 19298 16252 18595 16352 18595 16352 L 18595 3675 Z M 2972 1815 L 2972 0 L 21600 0 L 21600 14392 C 20800 14392 20000 14467 20000 14467 L 20000 1815 Z","stroked":false,"w":21600,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":21600,"path":"M 0 3675 L 18595 3675 L 18595 18022 C 9298 18022 9298 23542 0 20782 Z M 1532 3675 L 1532 1815 L 20000 1815 L 20000 16252 C 19298 16252 18595 16352 18595 16352 M 2972 1815 L 2972 0 L 21600 0 L 21600 14392 C 20800 14392 20000 14467 20000 14467","stroked":true,"w":21600,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":21600,"path":"M 0 20782 C 9298 23542 9298 18022 18595 18022 L 18595 16352 C 18595 16352 19298 16252 20000 16252 L 20000 14467 C 20000 14467 20800 14392 21600 14392 L 21600 0 L 2972 0 L 2972 1815 L 1532 1815 L 1532 3675 L 0 3675 Z","stroked":false,"w":21600,"windingRule":1}],"adjusts":[]},"flowChartInternalStorage":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":false,"w":1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":8,"path":"M 1 0 L 1 8 M 0 1 L 8 1","stroked":true,"w":8,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"flowChartPunchedTape":{"guides":["y2:*/ h 9 10","ib:*/ h 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":20,"path":"M 0 2 A 5 2 cd2 -10800000 A 5 2 cd2 cd2 L 20 18 A 5 2 0 -10800000 A 5 2 0 cd2 Z","stroked":true,"w":20,"windingRule":1}],"adjusts":[]},"snip2SameRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","tx1:*/ ss a1 100000","tx2:+- r 0 tx1","bx1:*/ ss a2 100000","bx2:+- r 0 bx1","by1:+- b 0 bx1","d:+- tx1 0 bx1","dx:?: d tx1 bx1","il:*/ dx 1 2","ir:+- r 0 il","it:*/ tx1 1 2","ib:+/ by1 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M tx1 t L tx2 t L r tx1 L r by1 L bx2 b L bx1 b L l by1 L l tx1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"actionButtonBeginning":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 8","g15:*/ g13 1 4","g16:+- g11 g14 0","g17:+- g11 g15 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g11 g9 L g11 g10 L g16 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g11 g9 L g11 g10 L g16 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g17 vc L g12 g9 L g12 g10 Z M g16 g9 L g16 g10 L g11 g10 L g11 g9 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartTerminator":{"guides":["il:*/ w 1018 21600","ir:*/ w 20582 21600","it:*/ h 3163 21600","ib:*/ h 18437 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 3475 0 L 18125 0 A 3475 10800 3cd4 cd2 L 3475 21600 A 3475 10800 cd4 cd2 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"notchedRightArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx2:*/ ss a2 100000","x2:+- r 0 dx2","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","x1:*/ dy1 dx2 hd2","x3:+- r 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x2 y1 L x2 t L r vc L x2 b L x2 y2 L l y2 L x1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"actionButtonEnd":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 3 4","g15:*/ g13 7 8","g16:+- g11 g14 0","g17:+- g11 g15 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g16 vc L g11 g9 L g11 g10 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g16 vc L g11 g9 L g11 g10 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g16 vc L g11 g10 L g11 g9 Z M g17 g9 L g12 g9 L g12 g10 L g17 g10 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss w","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","x1:*/ ss a3 100000","dx2:*/ w a4 100000","x2:+- r 0 dx2","x3:+/ x2 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x1 y2 L x2 y2 L x2 t L r t L r b L x2 b L x2 y3 L x1 y3 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"mathEqual":{"guides":["a1:pin 0 adj1 36745","2a1:*/ a1 2 1","mAdj2:+- 100000 0 2a1","a2:pin 0 adj2 mAdj2","dy1:*/ h a1 100000","dy2:*/ h a2 200000","dx1:*/ w 73490 200000","y2:+- vc 0 dy2","y3:+- vc dy2 0","y1:+- y2 0 dy1","y4:+- y3 dy1 0","x1:+- hc 0 dx1","x2:+- hc dx1 0","yC1:+/ y1 y2 2","yC2:+/ y3 y4 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x2 y1 L x2 y2 L x1 y2 Z M x1 y3 L x2 y3 L x2 y4 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 11760"]},"sun":{"guides":["a:pin 12500 adj 46875","g0:+- 50000 0 a","g1:*/ g0 30274 32768","g2:*/ g0 12540 32768","g3:+- g1 50000 0","g4:+- g2 50000 0","g5:+- 50000 0 g1","g6:+- 50000 0 g2","g7:*/ g0 23170 32768","g8:+- 50000 g7 0","g9:+- 50000 0 g7","g10:*/ g5 3 4","g11:*/ g6 3 4","g12:+- g10 3662 0","g13:+- g11 3662 0","g14:+- g11 12500 0","g15:+- 100000 0 g10","g16:+- 100000 0 g12","g17:+- 100000 0 g13","g18:+- 100000 0 g14","ox1:*/ w 18436 21600","oy1:*/ h 3163 21600","ox2:*/ w 3163 21600","oy2:*/ h 18436 21600","x8:*/ w g8 100000","x9:*/ w g9 100000","x10:*/ w g10 100000","x12:*/ w g12 100000","x13:*/ w g13 100000","x14:*/ w g14 100000","x15:*/ w g15 100000","x16:*/ w g16 100000","x17:*/ w g17 100000","x18:*/ w g18 100000","x19:*/ w a 100000","wR:*/ w g0 100000","hR:*/ h g0 100000","y8:*/ h g8 100000","y9:*/ h g9 100000","y10:*/ h g10 100000","y12:*/ h g12 100000","y13:*/ h g13 100000","y14:*/ h g14 100000","y15:*/ h g15 100000","y16:*/ h g16 100000","y17:*/ h g17 100000","y18:*/ h g18 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r vc L x15 y18 L x15 y14 Z M ox1 oy1 L x16 y13 L x17 y12 Z M hc t L x18 y10 L x14 y10 Z M ox2 oy1 L x13 y12 L x12 y13 Z M l vc L x10 y14 L x10 y18 Z M ox2 oy2 L x12 y17 L x13 y16 Z M hc b L x14 y15 L x18 y15 Z M ox1 oy2 L x17 y16 L x16 y17 Z M x19 vc A wR hR cd2 21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"triangle":{"guides":["a:pin 0 adj 100000","x1:*/ w a 200000","x2:*/ w a 100000","x3:+- x1 wd2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"gear9":{"guides":["a1:pin 0 adj1 20000","a2:pin 0 adj2 2679","th:*/ ss a1 100000","lFD:*/ ss a2 100000","th2:*/ th 1 2","l2:*/ lFD 1 2","l3:+- th2 l2 0","rh:+- hd2 0 th","rw:+- wd2 0 th","dr:+- rw 0 rh","maxr:?: dr rh rw","ha:at2 maxr l3","aA1:+- 18600000 0 ha","aD1:+- 18600000 ha 0","ta11:cos rw aA1","ta12:sin rh aA1","bA1:at2 ta11 ta12","cta1:cos rh bA1","sta1:sin rw bA1","ma1:mod cta1 sta1 0","na1:*/ rw rh ma1","dxa1:cos na1 bA1","dya1:sin na1 bA1","xA1:+- hc dxa1 0","yA1:+- vc dya1 0","td11:cos rw aD1","td12:sin rh aD1","bD1:at2 td11 td12","ctd1:cos rh bD1","std1:sin rw bD1","md1:mod ctd1 std1 0","nd1:*/ rw rh md1","dxd1:cos nd1 bD1","dyd1:sin nd1 bD1","xD1:+- hc dxd1 0","yD1:+- vc dyd1 0","xAD1:+- xA1 0 xD1","yAD1:+- yA1 0 yD1","lAD1:mod xAD1 yAD1 0","a1:at2 yAD1 xAD1","dxF1:sin lFD a1","dyF1:cos lFD a1","xF1:+- xD1 dxF1 0","yF1:+- yD1 dyF1 0","xE1:+- xA1 0 dxF1","yE1:+- yA1 0 dyF1","yC1t:sin th a1","xC1t:cos th a1","yC1:+- yF1 yC1t 0","xC1:+- xF1 0 xC1t","yB1:+- yE1 yC1t 0","xB1:+- xE1 0 xC1t","aA2:+- 21000000 0 ha","aD2:+- 21000000 ha 0","ta21:cos rw aA2","ta22:sin rh aA2","bA2:at2 ta21 ta22","cta2:cos rh bA2","sta2:sin rw bA2","ma2:mod cta2 sta2 0","na2:*/ rw rh ma2","dxa2:cos na2 bA2","dya2:sin na2 bA2","xA2:+- hc dxa2 0","yA2:+- vc dya2 0","td21:cos rw aD2","td22:sin rh aD2","bD2:at2 td21 td22","ctd2:cos rh bD2","std2:sin rw bD2","md2:mod ctd2 std2 0","nd2:*/ rw rh md2","dxd2:cos nd2 bD2","dyd2:sin nd2 bD2","xD2:+- hc dxd2 0","yD2:+- vc dyd2 0","xAD2:+- xA2 0 xD2","yAD2:+- yA2 0 yD2","lAD2:mod xAD2 yAD2 0","a2:at2 yAD2 xAD2","dxF2:sin lFD a2","dyF2:cos lFD a2","xF2:+- xD2 dxF2 0","yF2:+- yD2 dyF2 0","xE2:+- xA2 0 dxF2","yE2:+- yA2 0 dyF2","yC2t:sin th a2","xC2t:cos th a2","yC2:+- yF2 yC2t 0","xC2:+- xF2 0 xC2t","yB2:+- yE2 yC2t 0","xB2:+- xE2 0 xC2t","swAng1:+- bA2 0 bD1","aA3:+- 1800000 0 ha","aD3:+- 1800000 ha 0","ta31:cos rw aA3","ta32:sin rh aA3","bA3:at2 ta31 ta32","cta3:cos rh bA3","sta3:sin rw bA3","ma3:mod cta3 sta3 0","na3:*/ rw rh ma3","dxa3:cos na3 bA3","dya3:sin na3 bA3","xA3:+- hc dxa3 0","yA3:+- vc dya3 0","td31:cos rw aD3","td32:sin rh aD3","bD3:at2 td31 td32","ctd3:cos rh bD3","std3:sin rw bD3","md3:mod ctd3 std3 0","nd3:*/ rw rh md3","dxd3:cos nd3 bD3","dyd3:sin nd3 bD3","xD3:+- hc dxd3 0","yD3:+- vc dyd3 0","xAD3:+- xA3 0 xD3","yAD3:+- yA3 0 yD3","lAD3:mod xAD3 yAD3 0","a3:at2 yAD3 xAD3","dxF3:sin lFD a3","dyF3:cos lFD a3","xF3:+- xD3 dxF3 0","yF3:+- yD3 dyF3 0","xE3:+- xA3 0 dxF3","yE3:+- yA3 0 dyF3","yC3t:sin th a3","xC3t:cos th a3","yC3:+- yF3 yC3t 0","xC3:+- xF3 0 xC3t","yB3:+- yE3 yC3t 0","xB3:+- xE3 0 xC3t","swAng2:+- bA3 0 bD2","aA4:+- 4200000 0 ha","aD4:+- 4200000 ha 0","ta41:cos rw aA4","ta42:sin rh aA4","bA4:at2 ta41 ta42","cta4:cos rh bA4","sta4:sin rw bA4","ma4:mod cta4 sta4 0","na4:*/ rw rh ma4","dxa4:cos na4 bA4","dya4:sin na4 bA4","xA4:+- hc dxa4 0","yA4:+- vc dya4 0","td41:cos rw aD4","td42:sin rh aD4","bD4:at2 td41 td42","ctd4:cos rh bD4","std4:sin rw bD4","md4:mod ctd4 std4 0","nd4:*/ rw rh md4","dxd4:cos nd4 bD4","dyd4:sin nd4 bD4","xD4:+- hc dxd4 0","yD4:+- vc dyd4 0","xAD4:+- xA4 0 xD4","yAD4:+- yA4 0 yD4","lAD4:mod xAD4 yAD4 0","a4:at2 yAD4 xAD4","dxF4:sin lFD a4","dyF4:cos lFD a4","xF4:+- xD4 dxF4 0","yF4:+- yD4 dyF4 0","xE4:+- xA4 0 dxF4","yE4:+- yA4 0 dyF4","yC4t:sin th a4","xC4t:cos th a4","yC4:+- yF4 yC4t 0","xC4:+- xF4 0 xC4t","yB4:+- yE4 yC4t 0","xB4:+- xE4 0 xC4t","swAng3:+- bA4 0 bD3","aA5:+- 6600000 0 ha","aD5:+- 6600000 ha 0","ta51:cos rw aA5","ta52:sin rh aA5","bA5:at2 ta51 ta52","td51:cos rw aD5","td52:sin rh aD5","bD5:at2 td51 td52","xD5:+- w 0 xA4","xC5:+- w 0 xB4","xB5:+- w 0 xC4","swAng4:+- bA5 0 bD4","aD6:+- 9000000 ha 0","td61:cos rw aD6","td62:sin rh aD6","bD6:at2 td61 td62","xD6:+- w 0 xA3","xC6:+- w 0 xB3","xB6:+- w 0 xC3","aD7:+- 11400000 ha 0","td71:cos rw aD7","td72:sin rh aD7","bD7:at2 td71 td72","xD7:+- w 0 xA2","xC7:+- w 0 xB2","xB7:+- w 0 xC2","aD8:+- 13800000 ha 0","td81:cos rw aD8","td82:sin rh aD8","bD8:at2 td81 td82","xA8:+- w 0 xD1","xD8:+- w 0 xA1","xC8:+- w 0 xB1","xB8:+- w 0 xC1","aA9:+- 3cd4 0 ha","aD9:+- 3cd4 ha 0","td91:cos rw aD9","td92:sin rh aD9","bD9:at2 td91 td92","ctd9:cos rh bD9","std9:sin rw bD9","md9:mod ctd9 std9 0","nd9:*/ rw rh md9","dxd9:cos nd9 bD9","dyd9:sin nd9 bD9","xD9:+- hc dxd9 0","yD9:+- vc dyd9 0","ta91:cos rw aA9","ta92:sin rh aA9","bA9:at2 ta91 ta92","xA9:+- hc 0 dxd9","xF9:+- xD9 0 lFD","xE9:+- xA9 lFD 0","yC9:+- yD9 0 th","swAng5:+- bA9 0 bD8","xCxn1:+/ xB1 xC1 2","yCxn1:+/ yB1 yC1 2","xCxn2:+/ xB2 xC2 2","yCxn2:+/ yB2 yC2 2","xCxn3:+/ xB3 xC3 2","yCxn3:+/ yB3 yC3 2","xCxn4:+/ xB4 xC4 2","yCxn4:+/ yB4 yC4 2","xCxn5:+/ r 0 xCxn4","xCxn6:+/ r 0 xCxn3","xCxn7:+/ r 0 xCxn2","xCxn8:+/ r 0 xCxn1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA1 yA1 L xB1 yB1 L xC1 yC1 L xD1 yD1 A rw rh bD1 swAng1 L xB2 yB2 L xC2 yC2 L xD2 yD2 A rw rh bD2 swAng2 L xB3 yB3 L xC3 yC3 L xD3 yD3 A rw rh bD3 swAng3 L xB4 yB4 L xC4 yC4 L xD4 yD4 A rw rh bD4 swAng4 L xB5 yC4 L xC5 yB4 L xD5 yA4 A rw rh bD5 swAng3 L xB6 yC3 L xC6 yB3 L xD6 yA3 A rw rh bD6 swAng2 L xB7 yC2 L xC7 yB2 L xD7 yA2 A rw rh bD7 swAng1 L xB8 yC1 L xC8 yB1 L xD8 yA1 A rw rh bD8 swAng5 L xE9 yC9 L xF9 yC9 L xD9 yD9 A rw rh bD9 swAng5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 10000","adj2:val 1763"]},"round1Rect":{"guides":["a:pin 0 adj 50000","dx1:*/ ss a 100000","x1:+- r 0 dx1","idx:*/ dx1 29289 100000","ir:+- r 0 idx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t A dx1 dx1 3cd4 cd4 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"arc":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw11:+- enAng 0 stAng","sw12:+- sw11 21600000 0","swAng:?: sw11 sw11 sw12","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc dx2 0","y2:+- vc dy2 0","sw0:+- 21600000 0 stAng","da1:+- swAng 0 sw0","g1:max x1 x2","ir:?: da1 r g1","sw1:+- cd4 0 stAng","sw2:+- 27000000 0 stAng","sw3:?: sw1 sw1 sw2","da2:+- swAng 0 sw3","g5:max y1 y2","ib:?: da2 b g5","sw4:+- cd2 0 stAng","sw5:+- 32400000 0 stAng","sw6:?: sw4 sw4 sw5","da3:+- swAng 0 sw6","g9:min x1 x2","il:?: da3 l g9","sw7:+- 3cd4 0 stAng","sw8:+- 37800000 0 stAng","sw9:?: sw7 sw7 sw8","da4:+- swAng 0 sw9","g13:min y1 y2","it:?: da4 t g13","cang1:+- stAng 0 cd4","cang2:+- enAng cd4 0","cang3:+/ cang1 cang2 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L hc vc Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16200000","adj2:val 0"]},"upDownArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 50000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss hd2","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:*/ ss a3 100000","y4:+- b 0 y1","dy2:*/ h a4 200000","y2:+- vc 0 dy2","y3:+- vc dy2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L hc t L x4 y1 L x3 y1 L x3 y2 L r y2 L r y3 L x3 y3 L x3 y4 L x4 y4 L hc b L x1 y4 L x2 y4 L x2 y3 L l y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 48123"]},"leftBrace":{"guides":["a2:pin 0 adj2 100000","q1:+- 100000 0 a2","q2:min q1 a2","q3:*/ q2 1 2","maxAdj1:*/ q3 h ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","y3:*/ h a2 100000","y4:+- y3 y1 0","dx1:cos wd2 2700000","dy1:sin y1 2700000","il:+- r 0 dx1","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A wd2 y1 cd4 cd4 L hc y4 A wd2 y1 0 -5400000 A wd2 y1 cd4 -5400000 L hc y1 A wd2 y1 cd2 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r b A wd2 y1 cd4 cd4 L hc y4 A wd2 y1 0 -5400000 A wd2 y1 cd4 -5400000 L hc y1 A wd2 y1 cd2 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 8333","adj2:val 50000"]},"flowChartMagneticTape":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0","ang1:at2 w h"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc b A wd2 hd2 cd4 cd4 A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 ang1 L r ib L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"rightBracket":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 100000","y2:+- b 0 y1","dx1:cos w 2700000","dy1:sin y1 2700000","ir:+- l dx1 0","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t A w y1 3cd4 cd4 L r y2 A w y1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t A w y1 3cd4 cd4 L r y2 A w y1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"nonIsoscelesTrapezoid":{"guides":["maxAdj:*/ 50000 w ss","a1:pin 0 adj1 maxAdj","a2:pin 0 adj2 maxAdj","x1:*/ ss a1 200000","x2:*/ ss a1 100000","dx3:*/ ss a2 100000","x3:+- r 0 dx3","x4:+/ r x3 2","il:*/ wd3 a1 maxAdj","adjm:max a1 a2","it:*/ hd3 adjm maxAdj","irt:*/ wd3 a2 maxAdj","ir:+- r 0 irt"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L x3 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000"]},"ellipseRibbon":{"guides":["a1:pin 0 adj1 100000","a2:pin 25000 adj2 75000","q10:+- 100000 0 a1","q11:*/ q10 1 2","q12:+- a1 0 q11","minAdj3:max 0 q12","a3:pin minAdj3 adj3 a1","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x3:+- x2 wd8 0","x4:+- r 0 x3","x5:+- r 0 x2","x6:+- r 0 wd8","dy1:*/ h a3 100000","f1:*/ 4 dy1 w","q1:*/ x3 x3 w","q2:+- x3 0 q1","y1:*/ f1 q2 1","cx1:*/ x3 1 2","cy1:*/ f1 cx1 1","cx2:+- r 0 cx1","q1:*/ h a1 100000","dy3:+- q1 0 dy1","q3:*/ x2 x2 w","q4:+- x2 0 q3","q5:*/ f1 q4 1","y3:+- q5 dy3 0","q6:+- dy1 dy3 y3","q7:+- q6 dy1 0","cy3:+- q7 dy3 0","rh:+- b 0 q1","q8:*/ dy1 14 16","y2:+/ q8 rh 2","y5:+- q5 rh 0","y6:+- y3 rh 0","cx4:*/ x2 1 2","q9:*/ f1 cx4 1","cy4:+- q9 rh 0","cx5:+- r 0 cx4","cy6:+- cy3 rh 0","y7:+- y1 dy3 0","cy7:+- q1 q1 y7","y8:+- b 0 dy1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r t L x6 y2 L r rh Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l rh L wd8 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y7 L x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 L x4 y7 Q hc cy7 x3 y7 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r t L x6 y2 L r rh Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l rh L wd8 y2 Z M x2 y5 L x2 y3 M x5 y3 L x5 y5 M x3 y1 L x3 y7 M x4 y7 L x4 y1","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 12500"]},"ribbon2":{"guides":["a1:pin 0 adj1 33333","a2:pin 25000 adj2 75000","x10:+- r 0 wd8","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x9:+- hc dx2 0","x3:+- x2 wd32 0","x8:+- x9 0 wd32","x5:+- x2 wd8 0","x6:+- x9 0 wd8","x4:+- x5 0 wd32","x7:+- x6 wd32 0","dy1:*/ h a1 200000","y1:+- b 0 dy1","dy2:*/ h a1 100000","y2:+- b 0 dy2","y4:+- t dy2 0","y3:+/ y4 b 2","hR:*/ h a1 400000","y6:+- b 0 hR","y7:+- y1 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x4 b A wd32 hR cd4 -10800000 L x3 y1 A wd32 hR cd4 cd2 L x8 y2 A wd32 hR 3cd4 cd2 L x7 y1 A wd32 hR 3cd4 -10800000 L r b L x10 y3 L r y4 L x9 y4 L x9 hR A wd32 hR 0 -5400000 L x3 t A wd32 hR 3cd4 -5400000 L x2 y4 L l y4 L wd8 y3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x5 y6 A wd32 hR 0 -5400000 L x3 y1 A wd32 hR cd4 cd2 L x5 y2 Z M x6 y6 A wd32 hR cd2 cd4 L x8 y1 A wd32 hR cd4 -10800000 L x6 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l b L wd8 y3 L l y4 L x2 y4 L x2 hR A wd32 hR cd2 cd4 L x8 t A wd32 hR 3cd4 cd4 L x9 y4 L x9 y4 L r y4 L x10 y3 L r b L x7 b A wd32 hR cd4 cd2 L x8 y1 A wd32 hR cd4 -10800000 L x3 y2 A wd32 hR 3cd4 -10800000 L x4 y1 A wd32 hR 3cd4 cd2 Z M x5 y2 L x5 y6 M x6 y6 L x6 y2 M x2 y7 L x2 y4 M x9 y4 L x9 y7","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 50000"]},"gear6":{"guides":["a1:pin 0 adj1 20000","a2:pin 0 adj2 5358","th:*/ ss a1 100000","lFD:*/ ss a2 100000","th2:*/ th 1 2","l2:*/ lFD 1 2","l3:+- th2 l2 0","rh:+- hd2 0 th","rw:+- wd2 0 th","dr:+- rw 0 rh","maxr:?: dr rh rw","ha:at2 maxr l3","aA1:+- 19800000 0 ha","aD1:+- 19800000 ha 0","ta11:cos rw aA1","ta12:sin rh aA1","bA1:at2 ta11 ta12","cta1:cos rh bA1","sta1:sin rw bA1","ma1:mod cta1 sta1 0","na1:*/ rw rh ma1","dxa1:cos na1 bA1","dya1:sin na1 bA1","xA1:+- hc dxa1 0","yA1:+- vc dya1 0","td11:cos rw aD1","td12:sin rh aD1","bD1:at2 td11 td12","ctd1:cos rh bD1","std1:sin rw bD1","md1:mod ctd1 std1 0","nd1:*/ rw rh md1","dxd1:cos nd1 bD1","dyd1:sin nd1 bD1","xD1:+- hc dxd1 0","yD1:+- vc dyd1 0","xAD1:+- xA1 0 xD1","yAD1:+- yA1 0 yD1","lAD1:mod xAD1 yAD1 0","a1:at2 yAD1 xAD1","dxF1:sin lFD a1","dyF1:cos lFD a1","xF1:+- xD1 dxF1 0","yF1:+- yD1 dyF1 0","xE1:+- xA1 0 dxF1","yE1:+- yA1 0 dyF1","yC1t:sin th a1","xC1t:cos th a1","yC1:+- yF1 yC1t 0","xC1:+- xF1 0 xC1t","yB1:+- yE1 yC1t 0","xB1:+- xE1 0 xC1t","aD6:+- 3cd4 ha 0","td61:cos rw aD6","td62:sin rh aD6","bD6:at2 td61 td62","ctd6:cos rh bD6","std6:sin rw bD6","md6:mod ctd6 std6 0","nd6:*/ rw rh md6","dxd6:cos nd6 bD6","dyd6:sin nd6 bD6","xD6:+- hc dxd6 0","yD6:+- vc dyd6 0","xA6:+- hc 0 dxd6","xF6:+- xD6 0 lFD","xE6:+- xA6 lFD 0","yC6:+- yD6 0 th","swAng1:+- bA1 0 bD6","aA2:+- 1800000 0 ha","aD2:+- 1800000 ha 0","ta21:cos rw aA2","ta22:sin rh aA2","bA2:at2 ta21 ta22","yA2:+- h 0 yD1","td21:cos rw aD2","td22:sin rh aD2","bD2:at2 td21 td22","yD2:+- h 0 yA1","yC2:+- h 0 yB1","yB2:+- h 0 yC1","xB2:val xC1","swAng2:+- bA2 0 bD1","aD3:+- cd4 ha 0","td31:cos rw aD3","td32:sin rh aD3","bD3:at2 td31 td32","yD3:+- h 0 yD6","yB3:+- h 0 yC6","aD4:+- 9000000 ha 0","td41:cos rw aD4","td42:sin rh aD4","bD4:at2 td41 td42","xD4:+- w 0 xD1","xC4:+- w 0 xC1","xB4:+- w 0 xB1","aD5:+- 12600000 ha 0","td51:cos rw aD5","td52:sin rh aD5","bD5:at2 td51 td52","xD5:+- w 0 xA1","xC5:+- w 0 xB1","xB5:+- w 0 xC1","xCxn1:+/ xB1 xC1 2","yCxn1:+/ yB1 yC1 2","yCxn2:+- b 0 yCxn1","xCxn4:+/ r 0 xCxn1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA1 yA1 L xB1 yB1 L xC1 yC1 L xD1 yD1 A rw rh bD1 swAng2 L xC1 yB2 L xB1 yC2 L xA1 yD2 A rw rh bD2 swAng1 L xF6 yB3 L xE6 yB3 L xA6 yD3 A rw rh bD3 swAng1 L xB4 yC2 L xC4 yB2 L xD4 yA2 A rw rh bD4 swAng2 L xB5 yC1 L xC5 yB1 L xD5 yA1 A rw rh bD5 swAng1 L xE6 yC6 L xF6 yC6 L xD6 yD6 A rw rh bD6 swAng1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 15000","adj2:val 3526"]},"leftRightUpArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q1:+- 100000 0 maxAdj1","maxAdj3:*/ q1 1 2","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 100000","x2:+- hc 0 dx2","x5:+- hc dx2 0","dx3:*/ ss a1 200000","x3:+- hc 0 dx3","x4:+- hc dx3 0","x6:+- r 0 x1","dy2:*/ ss a2 50000","y2:+- b 0 dy2","y4:+- b 0 dx2","y3:+- y4 0 dx3","y5:+- y4 dx3 0","il:*/ dx3 x1 dx2","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y4 L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L hc t L x5 x1 L x4 x1 L x4 y3 L x6 y3 L x6 y2 L r y4 L x6 b L x6 y5 L x1 y5 L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"curvedConnector3":{"guides":["x2:*/ w adj1 100000","x1:+/ l x2 2","x3:+/ r x2 2","y3:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x1 t x2 hd4 x2 vc C x2 y3 x3 b r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000"]},"curvedConnector2":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C wd2 t r hd2 r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"curvedConnector5":{"guides":["x3:*/ w adj1 100000","x6:*/ w adj3 100000","x1:+/ x3 x6 2","x2:+/ l x3 2","x4:+/ x3 x1 2","x5:+/ x6 x1 2","x7:+/ x6 r 2","y4:*/ h adj2 100000","y1:+/ t y4 2","y2:+/ t y1 2","y3:+/ y1 y4 2","y5:+/ b y4 2","y6:+/ y5 y4 2","y7:+/ y5 b 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x2 t x3 y2 x3 y1 C x3 y3 x4 y4 x1 y4 C x5 y4 x6 y6 x6 y5 C x6 y7 x7 b r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 50000"]},"downArrow":{"guides":["maxAdj2:*/ 100000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dy1:*/ ss a2 100000","y1:+- b 0 dy1","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy2:*/ x1 dy1 wd2","y2:+- y1 dy2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x1 y1 L x1 t L x2 t L x2 y1 L r y1 L hc b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"curvedConnector4":{"guides":["x2:*/ w adj1 100000","x1:+/ l x2 2","x3:+/ r x2 2","x4:+/ x2 x3 2","x5:+/ x3 r 2","y4:*/ h adj2 100000","y1:+/ t y4 2","y2:+/ t y1 2","y3:+/ y1 y4 2","y5:+/ b y4 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t C x1 t x2 y2 x2 y1 C x2 y3 x4 y4 x3 y4 C x5 y4 r y5 r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartOnlineStorage":{"guides":["x2:*/ w 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 1 0 L 6 0 A 1 3 3cd4 -10800000 L 1 6 A 1 3 cd4 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"actionButtonDocument":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","dx1:*/ ss 9 32","g11:+- hc 0 dx1","g12:+- hc dx1 0","g13:*/ ss 3 16","g14:+- g12 0 g13","g15:+- g9 g13 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g9 L g14 g9 L g12 g15 L g12 g10 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M g11 g9 L g14 g9 L g14 g15 L g12 g15 L g12 g10 L g11 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g14 g9 L g14 g15 L g12 g15 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g9 L g14 g9 L g12 g15 L g12 g10 L g11 g10 Z M g12 g15 L g14 g15 L g14 g9","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"mathDivide":{"guides":["a1:pin 1000 adj1 36745","ma1:+- 0 0 a1","ma3h:+/ 73490 ma1 4","ma3w:*/ 36745 w h","maxAdj3:min ma3h ma3w","a3:pin 1000 adj3 maxAdj3","m4a3:*/ -4 a3 1","maxAdj2:+- 73490 m4a3 a1","a2:pin 0 adj2 maxAdj2","dy1:*/ h a1 200000","yg:*/ h a2 100000","rad:*/ h a3 100000","dx1:*/ w 73490 200000","y3:+- vc 0 dy1","y4:+- vc dy1 0","a:+- yg rad 0","y2:+- y3 0 a","y1:+- y2 0 rad","y5:+- b 0 y1","x1:+- hc 0 dx1","x3:+- hc dx1 0","x2:+- hc 0 rad"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc y1 A rad rad 3cd4 21600000 Z M hc y5 A rad rad cd4 21600000 Z M x1 y3 L x3 y3 L x3 y4 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 5880","adj3:val 11760"]},"decagon":{"guides":["shd2:*/ hd2 vf 100000","dx1:cos wd2 2160000","dx2:cos wd2 4320000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy1:sin shd2 4320000","dy2:sin shd2 2160000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y2 L x2 y1 L x3 y1 L x4 y2 L r vc L x4 y3 L x3 y4 L x2 y4 L x1 y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["vf:val 105146"]},"leftArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx2:*/ ss a2 100000","x2:+- l dx2 0","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx1:*/ y1 dx2 hd2","x1:+- x2 0 dx1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x2 t L x2 y1 L r y1 L r y2 L x2 y2 L x2 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"flowChartAlternateProcess":{"guides":["x2:+- r 0 ssd6","y2:+- b 0 ssd6","il:*/ ssd6 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l ssd6 A ssd6 ssd6 cd2 cd4 L x2 t A ssd6 ssd6 3cd4 cd4 L r y2 A ssd6 ssd6 0 cd4 L ssd6 b A ssd6 ssd6 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"borderCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"flowChartConnector":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"borderCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"borderCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"diagStripe":{"guides":["a:pin 0 adj 100000","x2:*/ w a 100000","x1:*/ x2 1 2","x3:+/ x2 r 2","y2:*/ h a 100000","y1:*/ y2 1 2","y3:+/ y2 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 t L r t L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"chevron":{"guides":["maxAdj:*/ 100000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 100000","x2:+- r 0 x1","x3:*/ x2 1 2","dx:+- x2 0 x1","il:?: dx x1 l","ir:?: dx x2 r"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x2 t L r vc L x2 b L l b L x1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 50000"]},"cornerTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t L l dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L dx b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L r t L r dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r y1 L r b L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"mathMultiply":{"guides":["a1:pin 0 adj1 51965","th:*/ ss a1 100000","a:at2 w h","sa:sin 1 a","ca:cos 1 a","ta:tan 1 a","dl:mod w h 0","rw:*/ dl 51965 100000","lM:+- dl 0 rw","xM:*/ ca lM 2","yM:*/ sa lM 2","dxAM:*/ sa th 2","dyAM:*/ ca th 2","xA:+- xM 0 dxAM","yA:+- yM dyAM 0","xB:+- xM dxAM 0","yB:+- yM 0 dyAM","xBC:+- hc 0 xB","yBC:*/ xBC ta 1","yC:+- yBC yB 0","xD:+- r 0 xB","xE:+- r 0 xA","yFE:+- vc 0 yA","xFE:*/ yFE 1 ta","xF:+- xE 0 xFE","xL:+- xA xFE 0","yG:+- b 0 yA","yH:+- b 0 yB","yI:+- b 0 yC","xC2:+- r 0 xM","yC3:+- b 0 yM"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xA yA L xB yB L hc yC L xD yB L xE yA L xF vc L xE yG L xD yH L hc yI L xB yH L xA yG L xL vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"plaque":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 70711 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd4 -5400000 L x2 t A x1 x1 cd2 -5400000 L r y2 A x1 x1 3cd4 -5400000 L x1 b A x1 x1 0 -5400000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"trapezoid":{"guides":["maxAdj:*/ 50000 w ss","a:pin 0 adj maxAdj","x1:*/ ss a 200000","x2:*/ ss a 100000","x3:+- r 0 x2","x4:+- r 0 x1","il:*/ wd3 a maxAdj","it:*/ hd3 a maxAdj","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L x2 t L x3 t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"accentBorderCallout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"accentBorderCallout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"teardrop":{"guides":["a:pin 0 adj 200000","r2:sqrt 2","tw:*/ wd2 r2 1","th:*/ hd2 r2 1","sw:*/ tw a 100000","sh:*/ th a 100000","dx1:cos sw 2700000","dy1:sin sh 2700000","x1:+- hc dx1 0","y1:+- vc 0 dy1","x2:+/ hc x1 2","y2:+/ vc y1 2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 Q x2 t x1 y1 Q r y2 r vc A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 100000"]},"accentBorderCallout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 t Z L x1 b","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"bentConnector3":{"guides":["x1:*/ w adj1 100000"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 b L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000"]},"hexagon":{"guides":["maxAdj:*/ 50000 w ss","a:pin 0 adj maxAdj","shd2:*/ hd2 vf 100000","x1:*/ ss a 100000","x2:+- r 0 x1","dy1:sin shd2 3600000","y1:+- vc 0 dy1","y2:+- vc dy1 0","q1:*/ maxAdj -1 2","q2:+- a q1 0","q3:?: q2 4 2","q4:?: q2 3 2","q5:?: q2 q1 0","q6:+/ a q5 q1","q7:*/ q6 q4 -1","q8:+- q3 q7 0","il:*/ w q8 24","it:*/ h q8 24","ir:+- r 0 il","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x2 y1 L r vc L x2 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000","vf:val 115470"]},"bentConnector2":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftBracket":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 100000","y2:+- b 0 y1","dx1:cos w 2700000","dy1:sin y1 2700000","il:+- r 0 dx1","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M r b A w y1 cd4 cd4 L l y1 A w y1 cd2 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r b A w y1 cd4 cd4 L l y1 A w y1 cd2 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"mathNotEqual":{"guides":["a1:pin 0 adj1 50000","crAng:pin 4200000 adj2 6600000","2a1:*/ a1 2 1","maxAdj3:+- 100000 0 2a1","a3:pin 0 adj3 maxAdj3","dy1:*/ h a1 100000","dy2:*/ h a3 200000","dx1:*/ w 73490 200000","x1:+- hc 0 dx1","x8:+- hc dx1 0","y2:+- vc 0 dy2","y3:+- vc dy2 0","y1:+- y2 0 dy1","y4:+- y3 dy1 0","cadj2:+- crAng 0 cd4","xadj2:tan hd2 cadj2","len:mod xadj2 hd2 0","bhw:*/ len dy1 hd2","bhw2:*/ bhw 1 2","x7:+- hc xadj2 bhw2","dx67:*/ xadj2 y1 hd2","x6:+- x7 0 dx67","dx57:*/ xadj2 y2 hd2","x5:+- x7 0 dx57","dx47:*/ xadj2 y3 hd2","x4:+- x7 0 dx47","dx37:*/ xadj2 y4 hd2","x3:+- x7 0 dx37","dx27:*/ xadj2 2 1","x2:+- x7 0 dx27","rx7:+- x7 bhw 0","rx6:+- x6 bhw 0","rx5:+- x5 bhw 0","rx4:+- x4 bhw 0","rx3:+- x3 bhw 0","rx2:+- x2 bhw 0","dx7:*/ dy1 hd2 len","rxt:+- x7 dx7 0","lxt:+- rx7 0 dx7","rx:?: cadj2 rxt rx7","lx:?: cadj2 x7 lxt","dy3:*/ dy1 xadj2 len","dy4:+- 0 0 dy3","ry:?: cadj2 dy3 t","ly:?: cadj2 t dy4","dlx:+- w 0 rx","drx:+- w 0 lx","dly:+- h 0 ry","dry:+- h 0 ly","xC1:+/ rx lx 2","xC2:+/ drx dlx 2","yC1:+/ ry ly 2","yC2:+/ y1 y2 2","yC3:+/ y3 y4 2","yC4:+/ dry dly 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x6 y1 L lx ly L rx ry L rx6 y1 L x8 y1 L x8 y2 L rx5 y2 L rx4 y3 L x8 y3 L x8 y4 L rx3 y4 L drx dry L dlx dly L x3 y4 L x1 y4 L x1 y3 L x4 y3 L x5 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520","adj2:val 6600000","adj3:val 11760"]},"wedgeEllipseCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","sdx:*/ dxPos h 1","sdy:*/ dyPos w 1","pang:at2 sdx sdy","stAng:+- pang 660000 0","enAng:+- pang 0 660000","dx1:cos wd2 stAng","dy1:sin hd2 stAng","x1:+- hc dx1 0","y1:+- vc dy1 0","dx2:cos wd2 enAng","dy2:sin hd2 enAng","x2:+- hc dx2 0","y2:+- vc dy2 0","stAng1:at2 dx1 dy1","enAng1:at2 dx2 dy2","swAng1:+- enAng1 0 stAng1","swAng2:+- swAng1 21600000 0","swAng:?: swAng1 swAng1 swAng2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xPos yPos L x1 y1 A wd2 hd2 stAng1 swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500"]},"pie":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw1:+- enAng 0 stAng","sw2:+- sw1 21600000 0","swAng:?: sw1 sw1 sw2","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","x1:+- hc dx1 0","y1:+- vc dy1 0","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x2:+- hc dx2 0","y2:+- vc dy2 0","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L hc vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 0","adj2:val 16200000"]},"cloud":{"guides":["il:*/ w 2977 21600","it:*/ h 3262 21600","ir:*/ w 17087 21600","ib:*/ h 17337 21600","g27:*/ w 67 21600","g28:*/ h 21577 21600","g29:*/ w 21582 21600","g30:*/ h 1235 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":43200,"path":"M 3900 14370 A 6753 9190 -11429249 7426832 A 5333 7267 -8646143 5396714 A 4365 5945 -8748475 5983381 A 4857 6595 -7859164 7034504 A 5333 7273 -4722533 6541615 A 6775 9220 -2776035 7816140 A 5785 7867 37501 6842000 A 6752 9215 1347096 6910353 A 7720 10543 3974558 4542661 A 4360 5918 -16496525 8804134 A 4345 5945 -14809710 9151131 Z","stroked":true,"w":43200,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":43200,"path":"M 4693 26177 A 4345 5945 5204520 1585770 M 6928 34899 A 4360 5918 4416628 686848 M 16478 39090 A 6752 9215 8257449 844866 M 28827 34751 A 6752 9215 387196 959901 M 34129 22954 A 5785 7867 -4217541 4255042 M 41798 15354 A 5333 7273 1819082 1665090 M 38324 5426 A 4857 6595 -824660 891534 M 29078 3952 A 4857 6595 -8950887 1091722 M 22141 4720 A 4365 5945 -9809656 1061181 M 14000 5192 A 6753 9190 -4002417 739161 M 4127 15789 A 6753 9190 9459261 711490","stroked":true,"w":43200,"windingRule":1}],"adjusts":[]},"curvedLeftArrow":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 a2","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","hR:+- hd2 0 q1","q7:*/ hR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idx:*/ q11 w q7","maxAdj3:*/ 100000 idx ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss a3 100000","y3:+- hR th 0","q2:*/ w w 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dy:*/ q5 hR w","y5:+- hR dy 0","y7:+- y3 dy 0","q6:+- aw 0 th","dh:*/ q6 1 2","y4:+- y5 0 dh","y8:+- y7 dh 0","aw2:*/ aw 1 2","y6:+- b 0 aw2","x1:+- l ah 0","swAng:at2 ah dy","mswAng:+- 0 0 swAng","ix:+- l idx 0","iy:+/ hR y3 2","q12:*/ th 1 2","dang2:at2 idx q12","swAng2:+- dang2 0 swAng","swAng3:+- swAng dang2 0","stAng3:+- 0 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y6 L x1 y4 L x1 y5 A w hR swAng swAng2 A w hR stAng3 swAng3 L x1 y8 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M r y3 A w hR 0 -5400000 L l t A w hR 3cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r y3 A w hR 0 -5400000 L l t A w hR 3cd4 cd4 L r y3 A w hR 0 swAng L x1 y8 L l y6 L x1 y4 L x1 y5 A w hR swAng swAng2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"bentConnector5":{"guides":["x1:*/ w adj1 100000","x3:*/ w adj3 100000","x2:+/ x1 x3 2","y2:*/ h adj2 100000","y1:+/ t y2 2","y3:+/ b y2 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 y2 L x3 y2 L x3 b L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 50000"]},"leftRightArrow":{"guides":["maxAdj2:*/ 50000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","x2:*/ ss a2 100000","x3:+- r 0 x2","dy:*/ h a1 200000","y1:+- vc 0 dy","y2:+- vc dy 0","dx1:*/ y1 x2 hd2","x1:+- x2 0 dx1","x4:+- x3 dx1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x2 t L x2 y1 L x3 y1 L x3 t L r vc L x3 b L x3 y2 L x2 y2 L x2 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"bentConnector4":{"guides":["x1:*/ w adj1 100000","x2:+/ x1 r 2","y2:*/ h adj2 100000","y1:+/ t y2 2"],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x1 t L x1 y2 L r y2 L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"noSmoking":{"guides":["a:pin 0 adj 50000","dr:*/ ss a 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","ang:at2 w h","ct:cos ihd2 ang","st:sin iwd2 ang","m:mod ct st 0","n:*/ iwd2 ihd2 m","drd2:*/ dr 1 2","dang:at2 n drd2","dang2:*/ dang 2 1","swAng:+- -10800000 dang2 0","t3:at2 w h","stAng1:+- t3 0 dang","stAng2:+- stAng1 0 cd2","ct1:cos ihd2 stAng1","st1:sin iwd2 stAng1","m1:mod ct1 st1 0","n1:*/ iwd2 ihd2 m1","dx1:cos n1 stAng1","dy1:sin n1 stAng1","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc 0 dx1","y2:+- vc 0 dy1","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z M x1 y1 A iwd2 ihd2 stAng1 swAng Z M x2 y2 A iwd2 ihd2 stAng2 swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 18750"]},"flowChartDecision":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 1 L 1 0 L 2 1 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"donut":{"guides":["a:pin 0 adj 50000","dr:*/ ss a 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z M dr vc A iwd2 ihd2 cd2 -5400000 A iwd2 ihd2 cd4 -5400000 A iwd2 ihd2 0 -5400000 A iwd2 ihd2 3cd4 -5400000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"ellipse":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftRightArrowCallout":{"guides":["maxAdj2:*/ 50000 h ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 50000 w ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss wd2","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dy1:*/ ss a2 100000","dy2:*/ ss a1 200000","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc dy2 0","y4:+- vc dy1 0","x1:*/ ss a3 100000","x4:+- r 0 x1","dx2:*/ w a4 200000","x2:+- hc 0 dx2","x3:+- hc dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y1 L x1 y2 L x2 y2 L x2 t L x3 t L x3 y2 L x4 y2 L x4 y1 L r vc L x4 y4 L x4 y3 L x3 y3 L x3 b L x2 b L x2 y3 L x1 y3 L x1 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 48123"]},"flowChartSummingJunction":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M il it L ir ib M ir it L il ib","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"squareTabs":{"guides":["md:mod w h 0","dx:*/ 1 md 20","y1:+- 0 b dx","x1:+- 0 r dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L dx t L dx dx L l dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L dx y1 L dx b L l b Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L r t L r dx L x1 dx Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L r y1 L r b L x1 b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"halfFrame":{"guides":["maxAdj2:*/ 100000 w ss","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","g1:*/ h x1 w","g2:+- h 0 g1","maxAdj1:*/ 100000 g2 ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","dx2:*/ y1 w h","x2:+- r 0 dx2","dy2:*/ x1 h w","y2:+- b 0 dy2","cx1:*/ x1 1 2","cy1:+/ y2 b 2","cx2:+/ x2 r 2","cy2:*/ y1 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L x2 y1 L x1 y1 L x1 y2 L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 33333","adj2:val 33333"]},"chartPlus":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 5 0 L 5 10 M 0 5 L 10 5","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"ribbon":{"guides":["a1:pin 0 adj1 33333","a2:pin 25000 adj2 75000","x10:+- r 0 wd8","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x9:+- hc dx2 0","x3:+- x2 wd32 0","x8:+- x9 0 wd32","x5:+- x2 wd8 0","x6:+- x9 0 wd8","x4:+- x5 0 wd32","x7:+- x6 wd32 0","y1:*/ h a1 200000","y2:*/ h a1 100000","y4:+- b 0 y2","y3:*/ y4 1 2","hR:*/ h a1 400000","y5:+- b 0 hR","y6:+- y2 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x4 t A wd32 hR 3cd4 cd2 L x3 y1 A wd32 hR 3cd4 -10800000 L x8 y2 A wd32 hR cd4 -10800000 L x7 y1 A wd32 hR cd4 cd2 L r t L x10 y3 L r y4 L x9 y4 L x9 y5 A wd32 hR 0 cd4 L x3 b A wd32 hR cd4 cd4 L x2 y4 L l y4 L wd8 y3 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x5 hR A wd32 hR 0 cd4 L x3 y1 A wd32 hR 3cd4 -10800000 L x5 y2 Z M x6 hR A wd32 hR cd2 -5400000 L x8 y1 A wd32 hR 3cd4 cd2 L x6 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L x4 t A wd32 hR 3cd4 cd2 L x3 y1 A wd32 hR 3cd4 -10800000 L x8 y2 A wd32 hR cd4 -10800000 L x7 y1 A wd32 hR cd4 cd2 L r t L x10 y3 L r y4 L x9 y4 L x9 y5 A wd32 hR 0 cd4 L x3 b A wd32 hR cd4 cd4 L x2 y4 L l y4 L wd8 y3 Z M x5 hR L x5 y2 M x6 y2 L x6 hR M x2 y4 L x2 y6 M x9 y6 L x9 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 50000"]},"star4":{"guides":["a:pin 0 adj 50000","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx:cos iwd2 2700000","sdy:sin ihd2 2700000","sx1:+- hc 0 sdx","sx2:+- hc sdx 0","sy1:+- vc 0 sdy","sy2:+- vc sdy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy1 L hc t L sx2 sy1 L r vc L sx2 sy2 L hc b L sx1 sy2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"star5":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:cos swd2 1080000","dx2:cos swd2 18360000","dy1:sin shd2 1080000","dy2:sin shd2 18360000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc 0 dy2","iwd2:*/ swd2 a 50000","ihd2:*/ shd2 a 50000","sdx1:cos iwd2 20520000","sdx2:cos iwd2 3240000","sdy1:sin ihd2 3240000","sdy2:sin ihd2 20520000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc sdx1 0","sy1:+- svc 0 sdy1","sy2:+- svc 0 sdy2","sy3:+- svc ihd2 0","yAdj:+- svc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L sx2 sy1 L hc t L sx3 sy1 L x4 y1 L sx4 sy2 L x3 y2 L hc sy3 L x2 y2 L sx1 sy2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 19098","hf:val 105146","vf:val 110557"]},"flowChartDelay":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L hc t A wd2 hd2 3cd4 cd2 L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"snip2DiagRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","lx1:*/ ss a1 100000","lx2:+- r 0 lx1","ly1:+- b 0 lx1","rx1:*/ ss a2 100000","rx2:+- r 0 rx1","ry1:+- b 0 rx1","d:+- lx1 0 rx1","dx:?: d lx1 rx1","il:*/ dx 1 2","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M lx1 t L rx2 t L r rx1 L r ly1 L lx2 b L rx1 b L l ry1 L l lx1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 0","adj2:val 16667"]},"star8":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 2700000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:sin hd2 2700000","y1:+- vc 0 dy1","y2:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 92388 100000","sdx2:*/ iwd2 38268 100000","sdy1:*/ ihd2 92388 100000","sdy2:*/ ihd2 38268 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc sdy2 0","sy4:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy2 L x1 y1 L sx2 sy1 L hc t L sx3 sy1 L x2 y1 L sx4 sy2 L r vc L sx4 sy3 L x2 y2 L sx3 sy4 L hc b L sx2 sy4 L x1 y2 L sx1 sy3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"heart":{"guides":["dx1:*/ w 49 48","dx2:*/ w 10 48","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:+- t 0 hd3","il:*/ w 1 6","ir:*/ w 5 6","ib:*/ h 2 3"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M hc hd4 C x3 y1 x4 hd4 hc b C x1 hd4 x2 y1 hc hd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"plus":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","d:+- w 0 h","il:?: d l x1","ir:?: d r x2","it:?: d x1 t","ib:?: d y2 b"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 L x1 x1 L x1 t L x2 t L x2 x1 L r x1 L r y2 L x2 y2 L x2 b L x1 b L x1 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"star6":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","dx1:cos swd2 1800000","x1:+- hc 0 dx1","x2:+- hc dx1 0","y2:+- vc hd4 0","iwd2:*/ swd2 a 50000","ihd2:*/ hd2 a 50000","sdx2:*/ iwd2 1 2","sx1:+- hc 0 iwd2","sx2:+- hc 0 sdx2","sx3:+- hc sdx2 0","sx4:+- hc iwd2 0","sdy1:sin ihd2 3600000","sy1:+- vc 0 sdy1","sy2:+- vc sdy1 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 hd4 L sx2 sy1 L hc t L sx3 sy1 L x2 hd4 L sx4 vc L x2 y2 L sx3 sy2 L hc b L sx2 sy2 L x1 y2 L sx1 vc Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 28868","hf:val 115470"]},"smileyFace":{"guides":["a:pin -4653 adj 4653","x1:*/ w 4969 21699","x2:*/ w 6215 21600","x3:*/ w 13135 21600","x4:*/ w 16640 21600","y1:*/ h 7570 21600","y3:*/ h 16515 21600","dy2:*/ h a 100000","y2:+- y3 0 dy2","y4:+- y3 dy2 0","dy3:*/ h a 50000","y5:+- y4 dy3 0","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0","wR:*/ w 1125 21600","hR:*/ h 1125 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x2 y1 A wR hR cd2 21600000 M x3 y1 A wR hR cd2 21600000","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y2 Q hc y5 x4 y2","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 21600000 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 4653"]},"star7":{"guides":["a:pin 0 adj 50000","swd2:*/ wd2 hf 100000","shd2:*/ hd2 vf 100000","svc:*/ vc vf 100000","dx1:*/ swd2 97493 100000","dx2:*/ swd2 78183 100000","dx3:*/ swd2 43388 100000","dy1:*/ shd2 62349 100000","dy2:*/ shd2 22252 100000","dy3:*/ shd2 90097 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc dx3 0","x5:+- hc dx2 0","x6:+- hc dx1 0","y1:+- svc 0 dy1","y2:+- svc dy2 0","y3:+- svc dy3 0","iwd2:*/ swd2 a 50000","ihd2:*/ shd2 a 50000","sdx1:*/ iwd2 97493 100000","sdx2:*/ iwd2 78183 100000","sdx3:*/ iwd2 43388 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc sdx3 0","sx5:+- hc sdx2 0","sx6:+- hc sdx1 0","sdy1:*/ ihd2 90097 100000","sdy2:*/ ihd2 22252 100000","sdy3:*/ ihd2 62349 100000","sy1:+- svc 0 sdy1","sy2:+- svc 0 sdy2","sy3:+- svc sdy3 0","sy4:+- svc ihd2 0","yAdj:+- svc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y2 L sx1 sy2 L x2 y1 L sx3 sy1 L hc t L sx4 sy1 L x5 y1 L sx6 sy2 L x6 y2 L sx5 sy3 L x4 y3 L hc sy4 L x3 y3 L sx2 sy3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 34601","hf:val 102572","vf:val 105210"]},"snipRoundRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","x1:*/ ss a1 100000","dx2:*/ ss a2 100000","x2:+- r 0 dx2","il:*/ x1 29289 100000","ir:+/ x2 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L x2 t L r dx2 L r b L l b L l x1 A x1 x1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 16667"]},"straightConnector1":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftCircularArrow":{"guides":["a5:pin 0 adj5 25000","maxAdj1:*/ a5 2 1","a1:pin 0 adj1 maxAdj1","enAng:pin 1 adj3 21599999","stAng:pin 0 adj4 21599999","th:*/ ss a1 100000","thh:*/ ss a5 100000","th2:*/ th 1 2","rw1:+- wd2 th2 thh","rh1:+- hd2 th2 thh","rw2:+- rw1 0 th","rh2:+- rh1 0 th","rw3:+- rw2 th2 0","rh3:+- rh2 th2 0","wtH:sin rw3 enAng","htH:cos rh3 enAng","dxH:cat2 rw3 htH wtH","dyH:sat2 rh3 htH wtH","xH:+- hc dxH 0","yH:+- vc dyH 0","rI:min rw2 rh2","u1:*/ dxH dxH 1","u2:*/ dyH dyH 1","u3:*/ rI rI 1","u4:+- u1 0 u3","u5:+- u2 0 u3","u6:*/ u4 u5 u1","u7:*/ u6 1 u2","u8:+- 1 0 u7","u9:sqrt u8","u10:*/ u4 1 dxH","u11:*/ u10 1 dyH","u12:+/ 1 u9 u11","u13:at2 1 u12","u14:+- u13 21600000 0","u15:?: u13 u13 u14","u16:+- u15 0 enAng","u17:+- u16 21600000 0","u18:?: u16 u16 u17","u19:+- u18 0 cd2","u20:+- u18 0 21600000","u21:?: u19 u20 u18","u22:abs u21","minAng:*/ u22 -1 1","u23:abs adj2","a2:*/ u23 -1 1","aAng:pin minAng a2 0","ptAng:+- enAng aAng 0","wtA:sin rw3 ptAng","htA:cos rh3 ptAng","dxA:cat2 rw3 htA wtA","dyA:sat2 rh3 htA wtA","xA:+- hc dxA 0","yA:+- vc dyA 0","wtE:sin rw1 stAng","htE:cos rh1 stAng","dxE:cat2 rw1 htE wtE","dyE:sat2 rh1 htE wtE","xE:+- hc dxE 0","yE:+- vc dyE 0","wtD:sin rw2 stAng","htD:cos rh2 stAng","dxD:cat2 rw2 htD wtD","dyD:sat2 rh2 htD wtD","xD:+- hc dxD 0","yD:+- vc dyD 0","dxG:cos thh ptAng","dyG:sin thh ptAng","xG:+- xH dxG 0","yG:+- yH dyG 0","dxB:cos thh ptAng","dyB:sin thh ptAng","xB:+- xH 0 dxB 0","yB:+- yH 0 dyB 0","sx1:+- xB 0 hc","sy1:+- yB 0 vc","sx2:+- xG 0 hc","sy2:+- yG 0 vc","rO:min rw1 rh1","x1O:*/ sx1 rO rw1","y1O:*/ sy1 rO rh1","x2O:*/ sx2 rO rw1","y2O:*/ sy2 rO rh1","dxO:+- x2O 0 x1O","dyO:+- y2O 0 y1O","dO:mod dxO dyO 0","q1:*/ x1O y2O 1","q2:*/ x2O y1O 1","DO:+- q1 0 q2","q3:*/ rO rO 1","q4:*/ dO dO 1","q5:*/ q3 q4 1","q6:*/ DO DO 1","q7:+- q5 0 q6","q8:max q7 0","sdelO:sqrt q8","ndyO:*/ dyO -1 1","sdyO:?: ndyO -1 1","q9:*/ sdyO dxO 1","q10:*/ q9 sdelO 1","q11:*/ DO dyO 1","dxF1:+/ q11 q10 q4","q12:+- q11 0 q10","dxF2:*/ q12 1 q4","adyO:abs dyO","q13:*/ adyO sdelO 1","q14:*/ DO dxO -1","dyF1:+/ q14 q13 q4","q15:+- q14 0 q13","dyF2:*/ q15 1 q4","q16:+- x2O 0 dxF1","q17:+- x2O 0 dxF2","q18:+- y2O 0 dyF1","q19:+- y2O 0 dyF2","q20:mod q16 q18 0","q21:mod q17 q19 0","q22:+- q21 0 q20","dxF:?: q22 dxF1 dxF2","dyF:?: q22 dyF1 dyF2","sdxF:*/ dxF rw1 rO","sdyF:*/ dyF rh1 rO","xF:+- hc sdxF 0","yF:+- vc sdyF 0","x1I:*/ sx1 rI rw2","y1I:*/ sy1 rI rh2","x2I:*/ sx2 rI rw2","y2I:*/ sy2 rI rh2","dxI:+- x2I 0 x1I","dyI:+- y2I 0 y1I","dI:mod dxI dyI 0","v1:*/ x1I y2I 1","v2:*/ x2I y1I 1","DI:+- v1 0 v2","v3:*/ rI rI 1","v4:*/ dI dI 1","v5:*/ v3 v4 1","v6:*/ DI DI 1","v7:+- v5 0 v6","v8:max v7 0","sdelI:sqrt v8","v9:*/ sdyO dxI 1","v10:*/ v9 sdelI 1","v11:*/ DI dyI 1","dxC1:+/ v11 v10 v4","v12:+- v11 0 v10","dxC2:*/ v12 1 v4","adyI:abs dyI","v13:*/ adyI sdelI 1","v14:*/ DI dxI -1","dyC1:+/ v14 v13 v4","v15:+- v14 0 v13","dyC2:*/ v15 1 v4","v16:+- x1I 0 dxC1","v17:+- x1I 0 dxC2","v18:+- y1I 0 dyC1","v19:+- y1I 0 dyC2","v20:mod v16 v18 0","v21:mod v17 v19 0","v22:+- v21 0 v20","dxC:?: v22 dxC1 dxC2","dyC:?: v22 dyC1 dyC2","sdxC:*/ dxC rw2 rI","sdyC:*/ dyC rh2 rI","xC:+- hc sdxC 0","yC:+- vc sdyC 0","ist0:at2 sdxC sdyC","ist1:+- ist0 21600000 0","istAng0:?: ist0 ist0 ist1","isw1:+- stAng 0 istAng0","isw2:+- isw1 21600000 0","iswAng0:?: isw1 isw1 isw2","istAng:+- istAng0 iswAng0 0","iswAng:+- 0 0 iswAng0","p1:+- xF 0 xC","p2:+- yF 0 yC","p3:mod p1 p2 0","p4:*/ p3 1 2","p5:+- p4 0 thh","xGp:?: p5 xF xG","yGp:?: p5 yF yG","xBp:?: p5 xC xB","yBp:?: p5 yC yB","en0:at2 sdxF sdyF","en1:+- en0 21600000 0","en2:?: en0 en0 en1","sw0:+- en2 0 stAng","sw1:+- sw0 0 21600000","swAng:?: sw0 sw1 sw0","stAng0:+- stAng swAng 0","swAng0:+- 0 0 swAng","wtI:sin rw3 stAng","htI:cos rh3 stAng","dxI:cat2 rw3 htI wtI","dyI:sat2 rh3 htI wtI","xI:+- hc dxI 0","yI:+- vc dyI 0","aI:+- stAng cd4 0","aA:+- ptAng 0 cd4","aB:+- ptAng cd2 0","idx:cos rw1 2700000","idy:sin rh1 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M xE yE L xD yD A rw2 rh2 istAng iswAng L xBp yBp L xA yA L xGp yGp L xF yF A rw1 rh1 stAng0 swAng0 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val -1142319","adj3:val 1142319","adj4:val 10800000","adj5:val 12500"]},"upArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss h","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","y1:*/ ss a3 100000","dy2:*/ h a4 100000","y2:+- b 0 dy2","y3:+/ y2 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L hc t L x4 y1 L x3 y1 L x3 y2 L r y2 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"actionButtonHelp":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g11:+- hc 0 dx2","g13:*/ ss 3 4","g14:*/ g13 1 7","g15:*/ g13 3 14","g16:*/ g13 2 7","g19:*/ g13 3 7","g20:*/ g13 4 7","g21:*/ g13 17 28","g23:*/ g13 21 28","g24:*/ g13 11 14","g27:+- g9 g16 0","g29:+- g9 g21 0","g30:+- g9 g23 0","g31:+- g9 g24 0","g33:+- g11 g15 0","g36:+- g11 g19 0","g37:+- g11 g20 0","g41:*/ g13 1 14","g42:*/ g13 3 28"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g33 g27 A g16 g16 cd2 cd2 A g14 g15 0 cd4 A g41 g42 3cd4 -5400000 L g37 g30 L g36 g30 L g36 g29 A g14 g15 cd2 cd4 A g41 g42 cd4 -5400000 A g14 g14 0 -10800000 Z M hc g31 A g42 g42 3cd4 21600000 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"flowChartProcess":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"irregularSeal2":{"guides":["x2:*/ w 9722 21600","x5:*/ w 5372 21600","x16:*/ w 11612 21600","x19:*/ w 14640 21600","y2:*/ h 1887 21600","y3:*/ h 6382 21600","y8:*/ h 12877 21600","y14:*/ h 19712 21600","y16:*/ h 18842 21600","y17:*/ h 15935 21600","y24:*/ h 6645 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 11462 4342 L 14790 0 L 14525 5777 L 18007 3172 L 16380 6532 L 21600 6645 L 16985 9402 L 18270 11290 L 16380 12310 L 18877 15632 L 14640 14350 L 14942 17370 L 12180 15935 L 11612 18842 L 9872 17370 L 8700 19712 L 7527 18125 L 4917 21600 L 4805 18240 L 1285 17825 L 3330 15370 L 0 12877 L 3935 11592 L 1172 8270 L 5372 7817 L 4502 3625 L 8550 6382 L 9722 1887 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"rtTriangle":{"guides":["it:*/ h 7 12","ir:*/ w 7 12","ib:*/ h 11 12"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l t L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"frame":{"guides":["a1:pin 0 adj1 50000","x1:*/ ss a1 100000","x4:+- r 0 x1","y4:+- b 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M x1 x1 L x1 y4 L x4 y4 L x4 x1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500"]},"irregularSeal1":{"guides":["x5:*/ w 4627 21600","x12:*/ w 8485 21600","x21:*/ w 16702 21600","x24:*/ w 14522 21600","y3:*/ h 6320 21600","y6:*/ h 8615 21600","y9:*/ h 13937 21600","y18:*/ h 13290 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 10800 5800 L 14522 0 L 14155 5325 L 18380 4457 L 16702 7315 L 21097 8137 L 17607 10475 L 21600 13290 L 16837 12942 L 18145 18095 L 14020 14457 L 13247 19737 L 10532 14935 L 8485 21600 L 7715 15627 L 4762 17617 L 5667 13937 L 135 14587 L 3722 11775 L 0 8615 L 4627 7617 L 370 2295 L 7312 6320 L 8352 2295 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"callout2":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 112500","adj6:val -46667"]},"callout3":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000","y3:*/ h adj5 100000","x3:*/ w adj6 100000","y4:*/ h adj7 100000","x4:*/ w adj8 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2 L x3 y3 L x4 y4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 18750","adj4:val -16667","adj5:val 100000","adj6:val -16667","adj7:val 112963","adj8:val -8333"]},"foldedCorner":{"guides":["a:pin 0 adj 50000","dy2:*/ ss a 100000","dy1:*/ dy2 1 5","x1:+- r 0 dy2","x2:+- x1 dy1 0","y2:+- b 0 dy2","y1:+- y2 dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r y2 L x1 b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x1 b L x2 y1 L r y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 b L x2 y1 L r y2 L x1 b L l b L l t L r t L r y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"callout1":{"guides":["y1:*/ h adj1 100000","x1:*/ w adj2 100000","y2:*/ h adj3 100000","x2:*/ w adj4 100000"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 y1 L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 18750","adj2:val -8333","adj3:val 112500","adj4:val -38333"]},"curvedUpArrow":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","a1:pin 0 adj1 100000","th:*/ ss a1 100000","aw:*/ ss a2 100000","q1:+/ th aw 4","wR:+- wd2 0 q1","q7:*/ wR 2 1","q8:*/ q7 q7 1","q9:*/ th th 1","q10:+- q8 0 q9","q11:sqrt q10","idy:*/ q11 h q7","maxAdj3:*/ 100000 idy ss","a3:pin 0 adj3 maxAdj3","ah:*/ ss adj3 100000","x3:+- wR th 0","q2:*/ h h 1","q3:*/ ah ah 1","q4:+- q2 0 q3","q5:sqrt q4","dx:*/ q5 wR h","x5:+- wR dx 0","x7:+- x3 dx 0","q6:+- aw 0 th","dh:*/ q6 1 2","x4:+- x5 0 dh","x8:+- x7 dh 0","aw2:*/ aw 1 2","x6:+- r 0 aw2","y1:+- t ah 0","swAng:at2 ah dx","mswAng:+- 0 0 swAng","iy:+- t idy 0","ix:+/ wR x3 2","q12:*/ th 1 2","dang2:at2 idy q12","swAng2:+- dang2 0 swAng","mswAng2:+- 0 0 swAng2","stAng3:+- cd4 0 swAng","swAng3:+- swAng dang2 0","stAng2:+- cd4 0 dang2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x6 t L x8 y1 L x7 y1 A wR h stAng3 swAng3 A wR h stAng2 swAng2 L x4 y1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M wR b A wR h cd4 cd4 L th t A wR h cd2 -5400000 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M ix iy A wR h stAng2 swAng2 L x4 y1 L x6 t L x8 y1 L x7 y1 A wR h stAng3 swAng L wR b A wR h cd4 cd4 L th t A wR h cd2 -5400000","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 25000"]},"line":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r b","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"downArrowCallout":{"guides":["maxAdj2:*/ 50000 w ss","a2:pin 0 adj2 maxAdj2","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","maxAdj3:*/ 100000 h ss","a3:pin 0 adj3 maxAdj3","q2:*/ a3 ss h","maxAdj4:+- 100000 0 q2","a4:pin 0 adj4 maxAdj4","dx1:*/ ss a2 100000","dx2:*/ ss a1 200000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc dx2 0","x4:+- hc dx1 0","dy3:*/ ss a3 100000","y3:+- b 0 dy3","y2:*/ h a4 100000","y1:*/ y2 1 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r y2 L x3 y2 L x3 y3 L x4 y3 L hc b L x1 y3 L x2 y3 L x2 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 64977"]},"rightBrace":{"guides":["a2:pin 0 adj2 100000","q1:+- 100000 0 a2","q2:min q1 a2","q3:*/ q2 1 2","maxAdj1:*/ q3 h ss","a1:pin 0 adj1 maxAdj1","y1:*/ ss a1 100000","y3:*/ h a2 100000","y2:+- y3 0 y1","y4:+- b 0 y1","dx1:cos wd2 2700000","dy1:sin y1 2700000","ir:+- l dx1 0","it:+- y1 0 dy1","ib:+- b dy1 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t A wd2 y1 3cd4 cd4 L hc y2 A wd2 y1 cd2 -5400000 A wd2 y1 3cd4 -5400000 L hc y4 A wd2 y1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t A wd2 y1 3cd4 cd4 L hc y2 A wd2 y1 cd2 -5400000 A wd2 y1 3cd4 -5400000 L hc y4 A wd2 y1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 8333","adj2:val 50000"]},"actionButtonSound":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 8","g15:*/ g13 5 16","g16:*/ g13 5 8","g17:*/ g13 11 16","g18:*/ g13 3 4","g19:*/ g13 7 8","g20:+- g9 g14 0","g21:+- g9 g15 0","g22:+- g9 g17 0","g23:+- g9 g19 0","g24:+- g11 g15 0","g25:+- g11 g16 0","g26:+- g11 g18 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g21 L g11 g22 L g24 g22 L g25 g10 L g25 g9 L g24 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 g21 L g11 g22 L g24 g22 L g25 g10 L g25 g9 L g24 g21 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g21 L g24 g21 L g25 g9 L g25 g10 L g24 g22 L g11 g22 Z M g26 g21 L g12 g20 M g26 vc L g12 vc M g26 g22 L g12 g23","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"quadArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","q1:+- 100000 0 maxAdj1","maxAdj3:*/ q1 1 2","a3:pin 0 adj3 maxAdj3","x1:*/ ss a3 100000","dx2:*/ ss a2 100000","x2:+- hc 0 dx2","x5:+- hc dx2 0","dx3:*/ ss a1 200000","x3:+- hc 0 dx3","x4:+- hc dx3 0","x6:+- r 0 x1","y2:+- vc 0 dx2","y5:+- vc dx2 0","y3:+- vc 0 dx3","y4:+- vc dx3 0","y6:+- b 0 x1","il:*/ dx3 x1 dx2","ir:+- r 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L x1 y2 L x1 y3 L x3 y3 L x3 x1 L x2 x1 L hc t L x5 x1 L x4 x1 L x4 y3 L x6 y3 L x6 y2 L r vc L x6 y5 L x6 y4 L x4 y4 L x4 y6 L x5 y6 L hc b L x2 y6 L x3 y6 L x3 y4 L x1 y4 L x1 y5 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 22500","adj2:val 22500","adj3:val 22500"]},"pieWedge":{"guides":["g1:cos w 13500000","g2:sin h 13500000","x1:+- r g1 0","y1:+- b g2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b A w h cd2 cd4 L r b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"wave":{"guides":["a1:pin 0 adj1 20000","a2:pin -10000 adj2 10000","y1:*/ h a1 100000","dy2:*/ y1 10 3","y2:+- y1 0 dy2","y3:+- y1 dy2 0","y4:+- b 0 y1","y5:+- y4 0 dy2","y6:+- y4 dy2 0","dx1:*/ w a2 100000","of2:*/ w a2 50000","x1:abs dx1","dx2:?: of2 0 of2","x2:+- l 0 dx2","dx5:?: of2 of2 0","x5:+- r 0 dx5","dx3:+/ dx2 x5 3","x3:+- x2 dx3 0","x4:+/ x3 x5 2","x6:+- l dx5 0","x10:+- r dx2 0","x7:+- x6 dx3 0","x8:+/ x7 x10 2","x9:+- r 0 x1","xAdj:+- hc dx1 0","xAdj2:+- hc 0 dx1","il:max x2 x6","ir:min x5 x10","it:*/ h a1 50000","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 y1 C x3 y2 x4 y3 x5 y1 L x10 y4 C x8 y6 x7 y5 x6 y4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 12500","adj2:val 0"]},"lightningBolt":{"guides":["x1:*/ w 5022 21600","x3:*/ w 8472 21600","x4:*/ w 8757 21600","x5:*/ w 10012 21600","x8:*/ w 12860 21600","x9:*/ w 13917 21600","x11:*/ w 16577 21600","y1:*/ h 3890 21600","y2:*/ h 6080 21600","y4:*/ h 7437 21600","y6:*/ h 9705 21600","y7:*/ h 12007 21600","y10:*/ h 14277 21600","y11:*/ h 14915 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 8472 0 L 12860 6080 L 11050 6797 L 16577 12007 L 14767 12877 L 21600 21600 L 10012 14915 L 12222 13987 L 5022 9705 L 7602 8382 L 0 3890 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"can":{"guides":["maxAdj:*/ 50000 h ss","a:pin 0 adj maxAdj","y1:*/ ss a 200000","y2:+- y1 y1 0","y3:+- b 0 y1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 A wd2 y1 cd2 -10800000 L r y3 A wd2 y1 0 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M l y1 A wd2 y1 cd2 cd2 A wd2 y1 0 cd2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M r y1 A wd2 y1 0 cd2 A wd2 y1 cd2 cd2 L r y3 A wd2 y1 0 cd2 L l y1","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 25000"]},"rect":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonMovie":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1455 21600","g15:*/ g13 1905 21600","g16:*/ g13 2325 21600","g17:*/ g13 16155 21600","g18:*/ g13 17010 21600","g19:*/ g13 19335 21600","g20:*/ g13 19725 21600","g21:*/ g13 20595 21600","g22:*/ g13 5280 21600","g23:*/ g13 5730 21600","g24:*/ g13 6630 21600","g25:*/ g13 7492 21600","g26:*/ g13 9067 21600","g27:*/ g13 9555 21600","g28:*/ g13 13342 21600","g29:*/ g13 14580 21600","g30:*/ g13 15592 21600","g31:+- g11 g14 0","g32:+- g11 g15 0","g33:+- g11 g16 0","g34:+- g11 g17 0","g35:+- g11 g18 0","g36:+- g11 g19 0","g37:+- g11 g20 0","g38:+- g11 g21 0","g39:+- g9 g22 0","g40:+- g9 g23 0","g41:+- g9 g24 0","g42:+- g9 g25 0","g43:+- g9 g26 0","g44:+- g9 g27 0","g45:+- g9 g28 0","g46:+- g9 g29 0","g47:+- g9 g30 0","g48:+- g9 g31 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M g11 g39 L g11 g44 L g31 g44 L g32 g43 L g33 g43 L g33 g47 L g35 g47 L g35 g45 L g36 g45 L g38 g46 L g12 g46 L g12 g41 L g38 g41 L g37 g42 L g35 g42 L g35 g41 L g34 g40 L g32 g40 L g31 g39 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M g11 g39 L g11 g44 L g31 g44 L g32 g43 L g33 g43 L g33 g47 L g35 g47 L g35 g45 L g36 g45 L g38 g46 L g12 g46 L g12 g41 L g38 g41 L g37 g42 L g35 g42 L g35 g41 L g34 g40 L g32 g40 L g31 g39 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M g11 g39 L g31 g39 L g32 g40 L g34 g40 L g35 g41 L g35 g42 L g37 g42 L g38 g41 L g12 g41 L g12 g46 L g38 g46 L g36 g45 L g35 g45 L g35 g47 L g33 g47 L g33 g43 L g32 g43 L g31 g44 L g11 g44 Z","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"actionButtonHome":{"guides":["dx2:*/ ss 3 8","g9:+- vc 0 dx2","g10:+- vc dx2 0","g11:+- hc 0 dx2","g12:+- hc dx2 0","g13:*/ ss 3 4","g14:*/ g13 1 16","g15:*/ g13 1 8","g16:*/ g13 3 16","g17:*/ g13 5 16","g18:*/ g13 7 16","g19:*/ g13 9 16","g20:*/ g13 11 16","g21:*/ g13 3 4","g22:*/ g13 13 16","g23:*/ g13 7 8","g24:+- g9 g14 0","g25:+- g9 g16 0","g26:+- g9 g17 0","g27:+- g9 g21 0","g28:+- g11 g15 0","g29:+- g11 g18 0","g30:+- g11 g19 0","g31:+- g11 g20 0","g32:+- g11 g22 0","g33:+- g11 g23 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L r t L r b L l b Z M hc g9 L g11 vc L g28 vc L g28 g10 L g33 g10 L g33 vc L g12 vc L g32 g26 L g32 g24 L g31 g24 L g31 g25 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M g32 g26 L g32 g24 L g31 g24 L g31 g25 Z M g28 vc L g28 g10 L g29 g10 L g29 g27 L g30 g27 L g30 g10 L g33 g10 L g33 vc Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M hc g9 L g11 vc L g12 vc Z M g29 g27 L g30 g27 L g30 g10 L g29 g10 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc g9 L g31 g25 L g31 g24 L g32 g24 L g32 g26 L g12 vc L g33 vc L g33 g10 L g28 g10 L g28 vc L g11 vc Z M g31 g25 L g32 g26 M g33 vc L g28 vc M g29 g10 L g29 g27 L g30 g27 L g30 g10","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"leftRightRibbon":{"guides":["a3:pin 0 adj3 33333","maxAdj1:+- 100000 0 a3","a1:pin 0 adj1 maxAdj1","w1:+- wd2 0 wd32","maxAdj2:*/ 100000 w1 ss","a2:pin 0 adj2 maxAdj2","x1:*/ ss a2 100000","x4:+- r 0 x1","dy1:*/ h a1 200000","dy2:*/ h a3 -200000","ly1:+- vc dy2 dy1","ry4:+- vc dy1 dy2","ly2:+- ly1 dy1 0","ry3:+- b 0 ly2","ly4:*/ ly2 2 1","ry1:+- b 0 ly4","ly3:+- ly4 0 ly1","ry2:+- b 0 ly3","hR:*/ a3 ss 400000","x2:+- hc 0 wd32","x3:+- hc wd32 0","y1:+- ly1 hR 0","y2:+- ry2 0 hR"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l ly2 L x1 t L x1 ly1 L hc ly1 A wd32 hR 3cd4 cd2 A wd32 hR 3cd4 -10800000 L x4 ry2 L x4 ry1 L r ry3 L x4 b L x4 ry4 L hc ry4 A wd32 hR cd4 cd4 L x2 ly3 L x1 ly3 L x1 ly4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y1 A wd32 hR 0 cd4 A wd32 hR 3cd4 -10800000 L x3 ry2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l ly2 L x1 t L x1 ly1 L hc ly1 A wd32 hR 3cd4 cd2 A wd32 hR 3cd4 -10800000 L x4 ry2 L x4 ry1 L r ry3 L x4 b L x4 ry4 L hc ry4 A wd32 hR cd4 cd4 L x2 ly3 L x1 ly3 L x1 ly4 Z M x3 y1 L x3 ry2 M x2 y2 L x2 ly3","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000","adj3:val 16667"]},"flowChartInputOutput":{"guides":["x3:*/ w 2 5","x4:*/ w 3 5","x5:*/ w 4 5","x6:*/ w 9 10"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":5,"path":"M 0 5 L 1 0 L 5 0 L 4 5 Z","stroked":true,"w":5,"windingRule":1}],"adjusts":[]},"snip1Rect":{"guides":["a:pin 0 adj 50000","dx1:*/ ss a 100000","x1:+- r 0 dx1","it:*/ dx1 1 2","ir:+/ x1 r 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l t L x1 t L r dx1 L r b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"lineInv":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L r t","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"upDownArrow":{"guides":["maxAdj2:*/ 50000 h ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","y2:*/ ss a2 100000","y3:+- b 0 y2","dx1:*/ w a1 200000","x1:+- hc 0 dx1","x2:+- hc dx1 0","dy1:*/ x1 y2 wd2","y1:+- y2 0 dy1","y4:+- y3 dy1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L hc t L r y2 L x2 y2 L x2 y3 L r y3 L hc b L l y3 L x1 y3 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"star24":{"guides":["a:pin 0 adj 50000","dx1:cos wd2 900000","dx2:cos wd2 1800000","dx3:cos wd2 2700000","dx4:val wd4","dx5:cos wd2 4500000","dy1:sin hd2 4500000","dy2:sin hd2 3600000","dy3:sin hd2 2700000","dy4:val hd4","dy5:sin hd2 900000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc 0 dx4","x5:+- hc 0 dx5","x6:+- hc dx5 0","x7:+- hc dx4 0","x8:+- hc dx3 0","x9:+- hc dx2 0","x10:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc 0 dy4","y5:+- vc 0 dy5","y6:+- vc dy5 0","y7:+- vc dy4 0","y8:+- vc dy3 0","y9:+- vc dy2 0","y10:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 99144 100000","sdx2:*/ iwd2 92388 100000","sdx3:*/ iwd2 79335 100000","sdx4:*/ iwd2 60876 100000","sdx5:*/ iwd2 38268 100000","sdx6:*/ iwd2 13053 100000","sdy1:*/ ihd2 99144 100000","sdy2:*/ ihd2 92388 100000","sdy3:*/ ihd2 79335 100000","sdy4:*/ ihd2 60876 100000","sdy5:*/ ihd2 38268 100000","sdy6:*/ ihd2 13053 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc 0 sdx5","sx6:+- hc 0 sdx6","sx7:+- hc sdx6 0","sx8:+- hc sdx5 0","sx9:+- hc sdx4 0","sx10:+- hc sdx3 0","sx11:+- hc sdx2 0","sx12:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc 0 sdy5","sy6:+- vc 0 sdy6","sy7:+- vc sdy6 0","sy8:+- vc sdy5 0","sy9:+- vc sdy4 0","sy10:+- vc sdy3 0","sy11:+- vc sdy2 0","sy12:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy6 L x1 y5 L sx2 sy5 L x2 y4 L sx3 sy4 L x3 y3 L sx4 sy3 L x4 y2 L sx5 sy2 L x5 y1 L sx6 sy1 L hc t L sx7 sy1 L x6 y1 L sx8 sy2 L x7 y2 L sx9 sy3 L x8 y3 L sx10 sy4 L x9 y4 L sx11 sy5 L x10 y5 L sx12 sy6 L r vc L sx12 sy7 L x10 y6 L sx11 sy8 L x9 y7 L sx10 sy9 L x8 y8 L sx9 sy10 L x7 y9 L sx8 sy11 L x6 y10 L sx7 sy12 L hc b L sx6 sy12 L x5 y10 L sx5 sy11 L x4 y9 L sx4 sy10 L x3 y8 L sx3 sy9 L x2 y7 L sx2 sy8 L x1 y6 L sx1 sy7 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"dodecagon":{"guides":["x1:*/ w 2894 21600","x2:*/ w 7906 21600","x3:*/ w 13694 21600","x4:*/ w 18706 21600","y1:*/ h 2894 21600","y2:*/ h 7906 21600","y3:*/ h 13694 21600","y4:*/ h 18706 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x1 y1 L x2 t L x3 t L x4 y1 L r y2 L r y3 L x4 y4 L x3 b L x2 b L x1 y4 L l y3 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"wedgeRoundRectCallout":{"guides":["dxPos:*/ w adj1 100000","dyPos:*/ h adj2 100000","xPos:+- hc dxPos 0","yPos:+- vc dyPos 0","dq:*/ dxPos h w","ady:abs dyPos","adq:abs dq","dz:+- ady 0 adq","xg1:?: dxPos 7 2","xg2:?: dxPos 10 5","x1:*/ w xg1 12","x2:*/ w xg2 12","yg1:?: dyPos 7 2","yg2:?: dyPos 10 5","y1:*/ h yg1 12","y2:*/ h yg2 12","t1:?: dxPos l xPos","xl:?: dz l t1","t2:?: dyPos x1 xPos","xt:?: dz t2 x1","t3:?: dxPos xPos r","xr:?: dz r t3","t4:?: dyPos xPos x1","xb:?: dz t4 x1","t5:?: dxPos y1 yPos","yl:?: dz y1 t5","t6:?: dyPos t yPos","yt:?: dz t6 t","t7:?: dxPos yPos y1","yr:?: dz y1 t7","t8:?: dyPos yPos b","yb:?: dz t8 b","u1:*/ ss adj3 100000","u2:+- r 0 u1","v2:+- b 0 u1","il:*/ u1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l u1 A u1 u1 cd2 cd4 L x1 t L xt yt L x2 t L u2 t A u1 u1 3cd4 cd4 L r y1 L xr yr L r y2 L r v2 A u1 u1 0 cd4 L x2 b L xb yb L x1 b L u1 b A u1 u1 cd4 cd4 L l y2 L xl yl L l y1 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val -20833","adj2:val 62500","adj3:val 16667"]},"round2DiagRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","x1:*/ ss a1 100000","y1:+- b 0 x1","a:*/ ss a2 100000","x2:+- r 0 a","y2:+- b 0 a","dx1:*/ x1 29289 100000","dx2:*/ a 29289 100000","d:+- dx1 0 dx2","dx:?: d dx1 dx2","ir:+- r 0 dx","ib:+- b 0 dx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 t L x2 t A a a 3cd4 cd4 L r y1 A x1 x1 0 cd4 L a b A a a cd4 cd4 L l x1 A x1 x1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"flowChartMagneticDrum":{"guides":["x2:*/ w 2 3"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 A 1 3 cd4 cd2 Z","stroked":false,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 5 6 A 1 3 cd4 cd2","stroked":true,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 1 0 L 5 0 A 1 3 3cd4 cd2 L 1 6 A 1 3 cd4 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"flowChartPreparation":{"guides":["x2:*/ w 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 5 L 2 0 L 8 0 L 10 5 L 8 10 L 2 10 Z","stroked":true,"w":10,"windingRule":1}],"adjusts":[]},"ellipseRibbon2":{"guides":["a1:pin 0 adj1 100000","a2:pin 25000 adj2 75000","q10:+- 100000 0 a1","q11:*/ q10 1 2","q12:+- a1 0 q11","minAdj3:max 0 q12","a3:pin minAdj3 adj3 a1","dx2:*/ w a2 200000","x2:+- hc 0 dx2","x3:+- x2 wd8 0","x4:+- r 0 x3","x5:+- r 0 x2","x6:+- r 0 wd8","dy1:*/ h a3 100000","f1:*/ 4 dy1 w","q1:*/ x3 x3 w","q2:+- x3 0 q1","u1:*/ f1 q2 1","y1:+- b 0 u1","cx1:*/ x3 1 2","cu1:*/ f1 cx1 1","cy1:+- b 0 cu1","cx2:+- r 0 cx1","q1:*/ h a1 100000","dy3:+- q1 0 dy1","q3:*/ x2 x2 w","q4:+- x2 0 q3","q5:*/ f1 q4 1","u3:+- q5 dy3 0","y3:+- b 0 u3","q6:+- dy1 dy3 u3","q7:+- q6 dy1 0","cu3:+- q7 dy3 0","cy3:+- b 0 cu3","rh:+- b 0 q1","q8:*/ dy1 14 16","u2:+/ q8 rh 2","y2:+- b 0 u2","u5:+- q5 rh 0","y5:+- b 0 u5","u6:+- u3 rh 0","y6:+- b 0 u6","cx4:*/ x2 1 2","q9:*/ f1 cx4 1","cu4:+- q9 rh 0","cy4:+- b 0 cu4","cx5:+- r 0 cx4","cu6:+- cu3 rh 0","cy6:+- b 0 cu6","u7:+- u1 dy3 0","y7:+- b 0 u7","cu7:+- q1 q1 u7","cy7:+- b 0 cu7"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b Q cx1 cy1 x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 Q cx2 cy1 r b L x6 y2 L r q1 Q cx5 cy4 x5 y5 L x5 y6 Q hc cy6 x2 y6 L x2 y5 Q cx4 cy4 l q1 L wd8 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M x3 y7 L x3 y1 L x2 y3 Q hc cy3 x5 y3 L x4 y1 L x4 y7 Q hc cy7 x3 y7 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l b L wd8 y2 L l q1 Q cx4 cy4 x2 y5 L x2 y6 Q hc cy6 x5 y6 L x5 y5 Q cx5 cy4 r q1 L x6 y2 L r b Q cx2 cy1 x4 y1 L x5 y3 Q hc cy3 x2 y3 L x3 y1 Q cx1 cy1 l b Z M x2 y3 L x2 y5 M x5 y5 L x5 y3 M x3 y7 L x3 y1 M x4 y1 L x4 y7","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 50000","adj3:val 12500"]},"round2SameRect":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","tx1:*/ ss a1 100000","tx2:+- r 0 tx1","bx1:*/ ss a2 100000","bx2:+- r 0 bx1","by1:+- b 0 bx1","d:+- tx1 0 bx1","tdx:*/ tx1 29289 100000","bdx:*/ bx1 29289 100000","il:?: d tdx bdx","ir:+- r 0 il","ib:+- b 0 bdx"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M tx1 t L tx2 t A tx1 tx1 3cd4 cd4 L r by1 A bx1 bx1 0 cd4 L bx1 b A bx1 bx1 cd4 cd4 L l tx1 A tx1 tx1 cd2 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 16667","adj2:val 0"]},"mathMinus":{"guides":["a1:pin 0 adj1 100000","dy1:*/ h a1 200000","dx1:*/ w 73490 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","x1:+- hc 0 dx1","x2:+- hc dx1 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 L x2 y1 L x2 y2 L x1 y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 23520"]},"blockArc":{"guides":["stAng:pin 0 adj1 21599999","istAng:pin 0 adj2 21599999","a3:pin 0 adj3 50000","sw11:+- istAng 0 stAng","sw12:+- sw11 21600000 0","swAng:?: sw11 sw11 sw12","iswAng:+- 0 0 swAng","wt1:sin wd2 stAng","ht1:cos hd2 stAng","wt3:sin wd2 istAng","ht3:cos hd2 istAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","dx3:cat2 wd2 ht3 wt3","dy3:sat2 hd2 ht3 wt3","x1:+- hc dx1 0","y1:+- vc dy1 0","x3:+- hc dx3 0","y3:+- vc dy3 0","dr:*/ ss a3 100000","iwd2:+- wd2 0 dr","ihd2:+- hd2 0 dr","wt2:sin iwd2 istAng","ht2:cos ihd2 istAng","wt4:sin iwd2 stAng","ht4:cos ihd2 stAng","dx2:cat2 iwd2 ht2 wt2","dy2:sat2 ihd2 ht2 wt2","dx4:cat2 iwd2 ht4 wt4","dy4:sat2 ihd2 ht4 wt4","x2:+- hc dx2 0","y2:+- vc dy2 0","x4:+- hc dx4 0","y4:+- vc dy4 0","sw0:+- 21600000 0 stAng","da1:+- swAng 0 sw0","g1:max x1 x2","g2:max x3 x4","g3:max g1 g2","ir:?: da1 r g3","sw1:+- cd4 0 stAng","sw2:+- 27000000 0 stAng","sw3:?: sw1 sw1 sw2","da2:+- swAng 0 sw3","g5:max y1 y2","g6:max y3 y4","g7:max g5 g6","ib:?: da2 b g7","sw4:+- cd2 0 stAng","sw5:+- 32400000 0 stAng","sw6:?: sw4 sw4 sw5","da3:+- swAng 0 sw6","g9:min x1 x2","g10:min x3 x4","g11:min g9 g10","il:?: da3 l g11","sw7:+- 3cd4 0 stAng","sw8:+- 37800000 0 stAng","sw9:?: sw7 sw7 sw8","da4:+- swAng 0 sw9","g13:min y1 y2","g14:min y3 y4","g15:min g13 g14","it:?: da4 t g15","x5:+/ x1 x4 2","y5:+/ y1 y4 2","x6:+/ x3 x2 2","y6:+/ y3 y2 2","cang1:+- stAng 0 cd4","cang2:+- istAng cd4 0","cang3:+/ cang1 cang2 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng L x2 y2 A iwd2 ihd2 istAng iswAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 10800000","adj2:val 0","adj3:val 25000"]},"flowChartPredefinedProcess":{"guides":["x2:*/ w 7 8"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":false,"w":1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":8,"path":"M 1 0 L 1 8 M 7 0 L 7 8","stroked":true,"w":8,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":1,"path":"M 0 0 L 1 0 L 1 1 L 0 1 Z","stroked":true,"w":1,"windingRule":1}],"adjusts":[]},"flowChartMagneticDisk":{"guides":["y3:*/ h 5 6"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":6,"path":"M 0 1 A 3 1 cd2 cd2 L 6 5 A 3 1 0 cd2 Z","stroked":false,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 6 1 A 3 1 0 cd2","stroked":true,"w":6,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":6,"path":"M 0 1 A 3 1 cd2 cd2 L 6 5 A 3 1 0 cd2 Z","stroked":true,"w":6,"windingRule":1}],"adjusts":[]},"flowChartOr":{"guides":["idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M hc t L hc b M l vc L r vc","stroked":true,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l vc A wd2 hd2 cd2 cd4 A wd2 hd2 3cd4 cd4 A wd2 hd2 0 cd4 A wd2 hd2 cd4 cd4 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"chartX":{"guides":[],"paths":[{"extrusionOk":false,"fill":"NONE","filled":false,"h":10,"path":"M 0 0 L 10 10 M 0 10 L 10 0","stroked":true,"w":10,"windingRule":1},{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 0 10 L 10 10 L 10 0 Z","stroked":false,"w":10,"windingRule":1}],"adjusts":[]},"flowChartOffpageConnector":{"guides":["y1:*/ h 4 5"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":10,"path":"M 0 0 L 10 0 L 10 8 L 5 10 L 0 8 Z","stroked":true,"w":10,"windingRule":1}],"adjusts":[]},"bevel":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 x1 L x2 x1 L x2 y2 L x1 y2 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN_LESS","filled":true,"h":-1,"path":"M l t L r t L x2 x1 L x1 x1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN_LESS","filled":true,"h":-1,"path":"M l b L x1 y2 L x2 y2 L r b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"LIGHTEN","filled":true,"h":-1,"path":"M l t L x1 x1 L x1 y2 L l b Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"DARKEN","filled":true,"h":-1,"path":"M r t L r b L x2 y2 L x2 x1 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M l t L r t L r b L l b Z M x1 x1 L x2 x1 L x2 y2 L x1 y2 Z M l t L x1 x1 M l b L x1 y2 M r t L x2 x1 M r b L x2 y2","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 12500"]},"rightArrow":{"guides":["maxAdj2:*/ 100000 w ss","a1:pin 0 adj1 100000","a2:pin 0 adj2 maxAdj2","dx1:*/ ss a2 100000","x1:+- r 0 dx1","dy1:*/ h a1 200000","y1:+- vc 0 dy1","y2:+- vc dy1 0","dx2:*/ y1 dx1 hd2","x2:+- x1 dx2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y1 L x1 y1 L x1 t L r vc L x1 b L x1 y2 L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 50000","adj2:val 50000"]},"bentArrow":{"guides":["a2:pin 0 adj2 50000","maxAdj1:*/ a2 2 1","a1:pin 0 adj1 maxAdj1","a3:pin 0 adj3 50000","th:*/ ss a1 100000","aw2:*/ ss a2 100000","th2:*/ th 1 2","dh2:+- aw2 0 th2","ah:*/ ss a3 100000","bw:+- r 0 ah","bh:+- b 0 dh2","bs:min bw bh","maxAdj4:*/ 100000 bs ss","a4:pin 0 adj4 maxAdj4","bd:*/ ss a4 100000","bd3:+- bd 0 th","bd2:max bd3 0","x3:+- th bd2 0","x4:+- r 0 ah","y3:+- dh2 th 0","y4:+- y3 dh2 0","y5:+- dh2 bd 0","y6:+- y3 bd2 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l b L l y5 A bd bd cd2 cd4 L x4 dh2 L x4 t L r aw2 L x4 y4 L x4 y3 L x3 y3 A bd2 bd2 3cd4 -5400000 L th b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000","adj4:val 43750"]},"diamond":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L hc t L r vc L hc b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":[]},"bracePair":{"guides":["a:pin 0 adj 25000","x1:*/ ss a 100000","x2:*/ ss a 50000","x3:+- r 0 x2","x4:+- r 0 x1","y2:+- vc 0 x1","y3:+- vc x1 0","y4:+- b 0 x1","it:*/ x1 29289 100000","il:+- x1 it 0","ir:+- r 0 il","ib:+- b 0 it"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x2 b A x1 x1 cd4 cd4 L x1 y3 A x1 x1 0 -5400000 A x1 x1 cd4 -5400000 L x1 x1 A x1 x1 cd2 cd4 L x3 t A x1 x1 3cd4 cd4 L x4 y2 A x1 x1 cd2 -5400000 A x1 x1 3cd4 -5400000 L x4 y4 A x1 x1 0 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x2 b A x1 x1 cd4 cd4 L x1 y3 A x1 x1 0 -5400000 A x1 x1 cd4 -5400000 L x1 x1 A x1 x1 cd2 cd4 M x3 t A x1 x1 3cd4 cd4 L x4 y2 A x1 x1 cd2 -5400000 A x1 x1 3cd4 -5400000 L x4 y4 A x1 x1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 8333"]},"flowChartDocument":{"guides":["y1:*/ h 17322 21600","y2:*/ h 20172 21600"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":21600,"path":"M 0 0 L 21600 0 L 21600 17322 C 10800 17322 10800 23922 0 20172 Z","stroked":true,"w":21600,"windingRule":1}],"adjusts":[]},"bentUpArrow":{"guides":["a1:pin 0 adj1 50000","a2:pin 0 adj2 50000","a3:pin 0 adj3 50000","y1:*/ ss a3 100000","dx1:*/ ss a2 50000","x1:+- r 0 dx1","dx3:*/ ss a2 100000","x3:+- r 0 dx3","dx2:*/ ss a1 200000","x2:+- x3 0 dx2","x4:+- x3 dx2 0","dy2:*/ ss a1 100000","y2:+- b 0 dy2","x0:*/ x4 1 2","y3:+/ y2 b 2","y15:+/ y1 b 2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l y2 L x2 y2 L x2 y1 L x1 y1 L x3 t L r y1 L x4 y1 L x4 b L l b Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 25000","adj2:val 25000","adj3:val 25000"]},"octagon":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 1 2","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 L x1 t L x2 t L r x1 L r y2 L x2 b L x1 b L l y2 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 29289"]},"chord":{"guides":["stAng:pin 0 adj1 21599999","enAng:pin 0 adj2 21599999","sw1:+- enAng 0 stAng","sw2:+- sw1 21600000 0","swAng:?: sw1 sw1 sw2","wt1:sin wd2 stAng","ht1:cos hd2 stAng","dx1:cat2 wd2 ht1 wt1","dy1:sat2 hd2 ht1 wt1","wt2:sin wd2 enAng","ht2:cos hd2 enAng","dx2:cat2 wd2 ht2 wt2","dy2:sat2 hd2 ht2 wt2","x1:+- hc dx1 0","y1:+- vc dy1 0","x2:+- hc dx2 0","y2:+- vc dy2 0","x3:+/ x1 x2 2","y3:+/ y1 y2 2","midAng0:*/ swAng 1 2","midAng:+- stAng midAng0 cd2","idx:cos wd2 2700000","idy:sin hd2 2700000","il:+- hc 0 idx","ir:+- hc idx 0","it:+- vc 0 idy","ib:+- vc idy 0"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M x1 y1 A wd2 hd2 stAng swAng Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj1:val 2700000","adj2:val 16200000"]},"flowChartCollate":{"guides":["ir:*/ w 3 4","ib:*/ h 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 1 L 2 2 L 0 2 L 1 1 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"flowChartExtract":{"guides":["x2:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 2 L 1 0 L 2 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]},"star32":{"guides":["a:pin 0 adj 50000","dx1:*/ wd2 98079 100000","dx2:*/ wd2 92388 100000","dx3:*/ wd2 83147 100000","dx4:cos wd2 2700000","dx5:*/ wd2 55557 100000","dx6:*/ wd2 38268 100000","dx7:*/ wd2 19509 100000","dy1:*/ hd2 98079 100000","dy2:*/ hd2 92388 100000","dy3:*/ hd2 83147 100000","dy4:sin hd2 2700000","dy5:*/ hd2 55557 100000","dy6:*/ hd2 38268 100000","dy7:*/ hd2 19509 100000","x1:+- hc 0 dx1","x2:+- hc 0 dx2","x3:+- hc 0 dx3","x4:+- hc 0 dx4","x5:+- hc 0 dx5","x6:+- hc 0 dx6","x7:+- hc 0 dx7","x8:+- hc dx7 0","x9:+- hc dx6 0","x10:+- hc dx5 0","x11:+- hc dx4 0","x12:+- hc dx3 0","x13:+- hc dx2 0","x14:+- hc dx1 0","y1:+- vc 0 dy1","y2:+- vc 0 dy2","y3:+- vc 0 dy3","y4:+- vc 0 dy4","y5:+- vc 0 dy5","y6:+- vc 0 dy6","y7:+- vc 0 dy7","y8:+- vc dy7 0","y9:+- vc dy6 0","y10:+- vc dy5 0","y11:+- vc dy4 0","y12:+- vc dy3 0","y13:+- vc dy2 0","y14:+- vc dy1 0","iwd2:*/ wd2 a 50000","ihd2:*/ hd2 a 50000","sdx1:*/ iwd2 99518 100000","sdx2:*/ iwd2 95694 100000","sdx3:*/ iwd2 88192 100000","sdx4:*/ iwd2 77301 100000","sdx5:*/ iwd2 63439 100000","sdx6:*/ iwd2 47140 100000","sdx7:*/ iwd2 29028 100000","sdx8:*/ iwd2 9802 100000","sdy1:*/ ihd2 99518 100000","sdy2:*/ ihd2 95694 100000","sdy3:*/ ihd2 88192 100000","sdy4:*/ ihd2 77301 100000","sdy5:*/ ihd2 63439 100000","sdy6:*/ ihd2 47140 100000","sdy7:*/ ihd2 29028 100000","sdy8:*/ ihd2 9802 100000","sx1:+- hc 0 sdx1","sx2:+- hc 0 sdx2","sx3:+- hc 0 sdx3","sx4:+- hc 0 sdx4","sx5:+- hc 0 sdx5","sx6:+- hc 0 sdx6","sx7:+- hc 0 sdx7","sx8:+- hc 0 sdx8","sx9:+- hc sdx8 0","sx10:+- hc sdx7 0","sx11:+- hc sdx6 0","sx12:+- hc sdx5 0","sx13:+- hc sdx4 0","sx14:+- hc sdx3 0","sx15:+- hc sdx2 0","sx16:+- hc sdx1 0","sy1:+- vc 0 sdy1","sy2:+- vc 0 sdy2","sy3:+- vc 0 sdy3","sy4:+- vc 0 sdy4","sy5:+- vc 0 sdy5","sy6:+- vc 0 sdy6","sy7:+- vc 0 sdy7","sy8:+- vc 0 sdy8","sy9:+- vc sdy8 0","sy10:+- vc sdy7 0","sy11:+- vc sdy6 0","sy12:+- vc sdy5 0","sy13:+- vc sdy4 0","sy14:+- vc sdy3 0","sy15:+- vc sdy2 0","sy16:+- vc sdy1 0","idx:cos iwd2 2700000","idy:sin ihd2 2700000","il:+- hc 0 idx","it:+- vc 0 idy","ir:+- hc idx 0","ib:+- vc idy 0","yAdj:+- vc 0 ihd2"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l vc L sx1 sy8 L x1 y7 L sx2 sy7 L x2 y6 L sx3 sy6 L x3 y5 L sx4 sy5 L x4 y4 L sx5 sy4 L x5 y3 L sx6 sy3 L x6 y2 L sx7 sy2 L x7 y1 L sx8 sy1 L hc t L sx9 sy1 L x8 y1 L sx10 sy2 L x9 y2 L sx11 sy3 L x10 y3 L sx12 sy4 L x11 y4 L sx13 sy5 L x12 y5 L sx14 sy6 L x13 y6 L sx15 sy7 L x14 y7 L sx16 sy8 L r vc L sx16 sy9 L x14 y8 L sx15 sy10 L x13 y9 L sx14 sy11 L x12 y10 L sx13 sy12 L x11 y11 L sx12 sy13 L x10 y12 L sx11 sy14 L x9 y13 L sx10 sy15 L x8 y14 L sx9 sy16 L hc b L sx8 sy16 L x7 y14 L sx7 sy15 L x6 y13 L sx6 sy14 L x5 y12 L sx5 sy13 L x4 y11 L sx4 sy12 L x3 y10 L sx3 sy11 L x2 y9 L sx2 sy10 L x1 y8 L sx1 sy9 Z","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 37500"]},"bracketPair":{"guides":["a:pin 0 adj 50000","x1:*/ ss a 100000","x2:+- r 0 x1","y2:+- b 0 x1","il:*/ x1 29289 100000","ir:+- r 0 il","ib:+- b 0 il"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":-1,"path":"M l x1 A x1 x1 cd2 cd4 L x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4 L x1 b A x1 x1 cd4 cd4 Z","stroked":false,"w":-1,"windingRule":1},{"extrusionOk":false,"fill":"NONE","filled":false,"h":-1,"path":"M x1 b A x1 x1 cd4 cd4 L l x1 A x1 x1 cd2 cd4 M x2 t A x1 x1 3cd4 cd4 L r y2 A x1 x1 0 cd4","stroked":true,"w":-1,"windingRule":1}],"adjusts":["adj:val 16667"]},"flowChartMerge":{"guides":["x2:*/ w 3 4"],"paths":[{"extrusionOk":false,"fill":"NORM","filled":true,"h":2,"path":"M 0 0 L 2 0 L 1 2 Z","stroked":true,"w":2,"windingRule":1}],"adjusts":[]}}; - -function geometryPaths(property, zoom) { - zoom = zoom || 1 - let geometry = property.geometry - let anchor = property.anchor ? [...property.anchor.map(s => s * zoom)] : property.anchor - if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { - return [] - } - let _anchor = [0, 0, anchor[2], anchor[3]] - if (geometry.name == 'custom') { - return getPaths(geometry.data.paths, true, _anchor, anchor, zoom) - } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { - let paths = [{ path: `M 0 0 L ${_anchor[2]} ${_anchor[3]}`, stroked: true, filled: true, w: -1, h: -1 }] - return getPaths(paths, false, _anchor, anchor) - } else { - let paths = calcPreGeometryPaths(geometry, _anchor) - return getPaths(paths, true, _anchor, anchor) - } -} - -function getPaths(paths, isEmu, anchor, real_anchor, zoom) { - let resultPaths = [] - for (let i = 0; i < paths.length; i++) { - let path = paths[i] - // console.log('path: ', path) - let scaleX = 1, scaleY = 1 - if (path.w > 0 && path.h > 0) { - if (path.w < 2000 && path.h < 2000) { - isEmu = false - } - let w = value2px(path.w, isEmu) - let h = value2px(path.h, isEmu) - scaleX = anchor[2] / w - scaleY = anchor[3] / h - } else if (zoom) { - scaleX = zoom - scaleY = zoom - } - let newPaths = [] - let split = path.path.replace(/\s+/g, ' ').trim().split(' ') - for (let j = 0; j < split.length; j++) { - switch (split[j]) { - case 'M': - case 'L': - newPaths.push(split[j]) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - break - case 'Q': - newPaths.push('Q') - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - break - case 'C': - newPaths.push('C') - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - newPaths.push(value2px(split[++j], isEmu)) - break - case 'Z': - newPaths.push('Z') - break - } - } - resultPaths.push({ - scaleX, - scaleY, - x: real_anchor[0], - y: real_anchor[1], - path: newPaths.join(' '), - stroked: path.stroked, - filled: path.filled - }) - } - return resultPaths -} - -function calcPreGeometryPaths(geometry, anchor) { - let pre = geometryMap[geometry.name] - if (!pre) { - console.log('未知形状:' + geometry.name) - return [] - } - // console.log(geometry.name) - let values = {} - let obj = { - x: value2emu(anchor[0]), - y: value2emu(anchor[1]), - width: value2emu(anchor[2]), - height: value2emu(anchor[3]), - centerX: value2emu(anchor[0] + anchor[2] / 2), - centerY: value2emu(anchor[1] + anchor[3] / 2), - maxX: value2emu(anchor[0] + anchor[2]), - maxY: value2emu(anchor[1] + anchor[3]), - values - } - if (pre.adjusts) { - for (let i = 0; i < pre.adjusts.length; i++) { - let adjust = pre.adjusts[i] - let idx = adjust.indexOf(':') - let name = adjust.substring(0, idx) - let fmla = adjust.substring(idx + 1) - let value = fmlaEvaluate(obj, fmla) - values[name] = value - } - } - if (geometry.avLst) { - for (let i = 0; i < geometry.avLst.length; i++) { - let adjust = geometry.avLst[i] - let idx = adjust.indexOf(':') - let name = adjust.substring(0, idx) - let fmla = adjust.substring(idx + 1) - let value = fmlaEvaluate(obj, fmla) - values[name] = value - } - } - if (pre.guides) { - for (let i = 0; i < pre.guides.length; i++) { - let adjust = pre.guides[i] - let idx = adjust.indexOf(':') - let name = adjust.substring(0, idx) - let fmla = adjust.substring(idx + 1) - let value = fmlaEvaluate(obj, fmla) - values[name] = value - } - } - let paths = pre.paths - let newPaths = [] - for (let i = 0; i < paths.length; i++) { - let path = { ...paths[i] } - let split = path.path.replace(/\s+/g, ' ').trim().split(' ') - let currentPoint = { x: obj.x, y: obj.y } - let newPath = [] - for (let j = 0; j < split.length; j++) { - switch (split[j]) { - case 'A': - let wr = pathEvaluate(obj, split[++j]) - let hr = pathEvaluate(obj, split[++j]) - let stAng = pathEvaluate(obj, split[++j]) - let swAng = pathEvaluate(obj, split[++j]) - let _paths = arcToBezierCurve(currentPoint, wr, hr, stAng, swAng) - // console.log('A: ', _paths) - let p = 0 - if (_paths[0] == 'M' && newPath.length > 0 && newPath[newPath.length - 1] != 'Z' && - valueEquals(newPath[newPath.length - 2], _paths[1]) && valueEquals(newPath[newPath.length - 1], _paths[2])) { - p = 3 - } - for (; p < _paths.length; p++) { - newPath.push(_paths[p]) - } - currentPoint.x = _paths[_paths.length - 2] - currentPoint.y = _paths[_paths.length - 1] - break - case 'M': - case 'L': - newPath.push(split[j]) - currentPoint.x = pathEvaluate(obj, split[++j]) - currentPoint.y = pathEvaluate(obj, split[++j]) - newPath.push(currentPoint.x) - newPath.push(currentPoint.y) - break - case 'Q': - newPath.push(split[j]) - newPath.push(pathEvaluate(obj, split[++j])) - newPath.push(pathEvaluate(obj, split[++j])) - currentPoint.x = pathEvaluate(obj, split[++j]) - currentPoint.y = pathEvaluate(obj, split[++j]) - newPath.push(currentPoint.x) - newPath.push(currentPoint.y) - break - case 'C': - newPath.push(split[j]) - newPath.push(pathEvaluate(obj, split[++j])) - newPath.push(pathEvaluate(obj, split[++j])) - newPath.push(pathEvaluate(obj, split[++j])) - newPath.push(pathEvaluate(obj, split[++j])) - currentPoint.x = pathEvaluate(obj, split[++j]) - currentPoint.y = pathEvaluate(obj, split[++j]) - newPath.push(currentPoint.x) - newPath.push(currentPoint.y) - break - case 'Z': - newPath.push(split[j]) - break - } - } - path.path = newPath.join(' ') - newPaths.push(path) - } - return newPaths -} - -function pathEvaluate(obj, value) { - if (obj.values && obj.values[value] != null) { - return obj.values[value] - } - let ss = Math.min(obj.width, obj.height) - switch (value) { - case 'l': - return obj.x - case 't': - return obj.y - case 'b': - return obj.maxY - case 'r': - return obj.maxX - case 'hc': - return obj.centerX - case 'vc': - return obj.centerY - case '3cd4': - return 1.62E7 - case '3cd8': - return 8100000 - case '5cd8': - return 1.35E7 - case '7cd8': - return 1.89E7 - case 'cd2': - return 1.08E7 - case 'cd4': - return 5400000 - case 'cd8': - return 2700000 - case 'ss': - return ss - case 'ssd2': - return ss / 2 - case 'ssd4': - return ss / 4 - case 'ssd6': - return ss / 6 - case 'ssd8': - return ss / 8 - case 'ssd16': - return ss / 16 - case 'ssd32': - return ss / 32 - case 'ls': - return Math.max(obj.width, obj.height) - case 'w': - return obj.width - case 'wd2': - return obj.width / 2 - case 'wd3': - return obj.width / 3 - case 'wd4': - return obj.width / 4 - case 'wd5': - return obj.width / 5 - case 'wd6': - return obj.width / 6 - case 'wd8': - return obj.width / 8 - case 'wd10': - return obj.width / 10 - case 'wd32': - return obj.width / 32 - case 'h': - return obj.height - case 'hd2': - return obj.height / 2 - case 'hd3': - return obj.height / 3 - case 'hd4': - return obj.height / 4 - case 'hd5': - return obj.height / 5 - case 'hd6': - return obj.height / 6 - case 'hd7': - return obj.height / 7 - case 'hd8': - return obj.height / 8 - default: - if (/^(-)?(\d+)(\.)?(\d+)?$/.test(value)) { - return +value - } else { - console.log('未知pathEval: ' + value) - return 0 - } - } -} - -function fmlaEvaluate(obj, fmla) { - let split = fmla.replace(/\s+/g, ' ').trim().split(' ') - let op = split[0] - let x = split.length > 1 ? pathEvaluate(obj, split[1]) : 0 - let y = split.length > 2 ? pathEvaluate(obj, split[2]) : 0 - let z = split.length > 3 ? pathEvaluate(obj, split[3]) : 0 - switch (op) { - case 'abs': - return Math.abs(x) - case '+/': - case 'adddiv': - return z == 0 ? 0 : (x + y) / z - case '+-': - case 'addsub': - return x + y - z - case 'at2': - return (Math.atan2(y, x) * 180 / Math.PI) * 60000 - case 'cos': - return x * Math.cos(y / 60000 / 180 * Math.PI) - case 'cat2': - return x * Math.cos(Math.atan2(z, y)) - case '?:': - case 'ifelse': - return x > 0 ? y : z - case 'val': - return x - case 'max': - return Math.max(x, y) - case 'min': - return Math.min(x, y) - case 'mod': - return Math.sqrt(x * x + y * y + z * z) - case '*/': - case 'muldiv': - return z == 0 ? 0 : x * y / z - case 'pin': - return Math.max(x, Math.min(y, z)) - case 'sat2': - return x * Math.sin(Math.atan2(z, y)) - case 'sin': - return x * Math.sin(y / 60000 / 180 * Math.PI) - case 'sqrt': - return Math.sqrt(x) - case 'tan': - return x * Math.tan(y / 60000 / 180 * Math.PI) - default: - console.log('未知op: ' + op, fmla) - return 0 - } -} - -function arcToBezierCurve(pt, wr, hr, stAng, swAng) { - let rx = wr - let ry = hr - let ooStart = stAng / 60000 - let ooExtent = swAng / 60000 - let start = convertOoxml2Angle(ooStart, rx, ry) - let extent = convertOoxml2Angle(ooStart + ooExtent, rx, ry) - start - let radStart = ooStart / 180 * Math.PI - let invStart = Math.atan2(rx * Math.sin(radStart), ry * Math.cos(radStart)) - let x0 = pt.x - rx * Math.cos(invStart) - rx - let y0 = pt.y - ry * Math.sin(invStart) - ry - let arc = { x: x0, y: y0, width: rx * 2, height: ry * 2, start: start, extent: extent, type: 0 } - return arcToBezierCurvePaths(arc) -} - -function arcToBezierCurvePaths(a) { - let x, y, w, h, angStRad, increment, cv - let arcSegs = 0, lineSegs = 0 - w = a.width / 2 - h = a.height / 2 - x = a.x + w - y = a.y + h - angStRad = -(a.start / 180 * Math.PI) - let ext = -a.extent - if (ext >= 360 || ext <= -360) { - arcSegs = 4 - increment = Math.PI / 2 - cv = 0.5522847498307933 - if (ext < 0) { - increment = -increment - cv = -cv - } - } else { - arcSegs = Math.ceil(Math.abs(ext) / 90) - increment = (ext / arcSegs) / 180 * Math.PI - let _increment = increment / 2 - cv = 4 / 3 * Math.sin(_increment) / (1 + Math.cos(_increment)) - if (cv == 0) { - arcSegs = 0 - } - } - lineSegs = a.type - if (w < 0 || h < 0) { - arcSegs = lineSegs = -1 - } - let paths = [] - let coords = [0, 0, 0, 0, 0, 0] - for (let index = 0; index <= arcSegs + lineSegs; index++) { - let angle = angStRad - if (index == 0) { - coords[0] = x + Math.cos(angle) * w - coords[1] = y + Math.sin(angle) * h - paths.push('M') - paths.push(coords[0]) - paths.push(coords[1]) - continue - } - if (index > arcSegs) { - if (index == arcSegs + lineSegs) { - paths.push('Z') - continue - } - coords[0] = x - coords[1] = y - paths.push('L') - paths.push(coords[0]) - paths.push(coords[1]) - continue - } - angle += increment * (index - 1) - let relx = Math.cos(angle) - let rely = Math.sin(angle) - coords[0] = x + (relx - cv * rely) * w - coords[1] = y + (rely + cv * relx) * h - angle += increment - relx = Math.cos(angle) - rely = Math.sin(angle) - coords[2] = x + (relx + cv * rely) * w - coords[3] = y + (rely - cv * relx) * h - coords[4] = x + relx * w - coords[5] = y + rely * h - paths.push('C') - paths.push(coords[0]) - paths.push(coords[1]) - paths.push(coords[2]) - paths.push(coords[3]) - paths.push(coords[4]) - paths.push(coords[5]) - } - return paths -} - -function convertOoxml2Angle(ooAngle, width, height) { - let aspect = height / width - let awtAngle = -ooAngle - let awtAngle2 = awtAngle % 360 - let awtAngle3 = awtAngle - awtAngle2 - switch (parseInt(awtAngle2 / 90)) { - case -3: - awtAngle3 -= 360 - awtAngle2 += 360 - break - case -2: - case -1: - awtAngle3 -= 180 - awtAngle2 += 180 - case 0: - break - default: - break - case 1: - case 2: - awtAngle3 += 180 - awtAngle2 -= 180 - break - case 3: - awtAngle3 += 360 - awtAngle2 -= 360 - } - awtAngle = (Math.atan2(Math.tan(awtAngle2 / 180 * Math.PI), aspect)) * 180 / Math.PI + awtAngle3 - return awtAngle -} - -function value2px(v, isEmu) { - if (isEmu) { - return +v / 12700 - } else { - return +v - } -} - -function value2emu(v) { - return +v * 12700 -} - -function valueEquals(v1, v2) { - if (v1 == v2) { - return true - } - if (v1 != null && v2 == null || v1 == null && v2 != null) { - return false - } - if (v1 > 1000 && Math.abs(v1 - v2) < 0.001) { - return true - } - let f1 = v1.toFixed(6) - let f2 = v2.toFixed(6) - if (f1 == f2) { - return true - } - if (f1 == '0.000000' && f2 == '-0.000000' || f1 == '-0.000000' && f2 == '0.000000') { - return true - } - return false -} - -export { geometryPaths } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js deleted file mode 100644 index 54e8d72..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2canvas.js +++ /dev/null @@ -1,1328 +0,0 @@ -/* eslint-disable no-unused-vars */ -/* eslint-disable no-self-assign */ -import { geometryPaths } from './geometry.js' -import { drawChart } from './chart.js' - -function Ppt2Canvas(_canvas, imageCrossOrigin) { - var canvas = (typeof _canvas == 'string') ? document.getElementById(_canvas) : _canvas - var ctx = canvas.getContext('2d') - var pptx = null - var page = null - var idMap = {} - var imageCache = {} - var pageIndex = 0 - var templateHandle = null - - this.drawPptx = async (pptxObj, pageIdx) => { - idMap = {} - imageCache = {} - pptx = pptxObj - pageIndex = pageIdx - page = pptxObj.pages[pageIdx] - canvas.width = canvas.width - canvas.height = canvas.height - ctx.scaleX = canvas.width / pptxObj.width - ctx.scaleY = canvas.height / pptxObj.height - ctx.scale(ctx.scaleX, ctx.scaleY) - ctx.interior = ctx._interior = null - let placeholder = {} - let slideMasterIdx = page.extInfo.slideMasterIdx - if (slideMasterIdx != null && pptxObj.slideMasters) { - let slideMaster = pptxObj.slideMasters[slideMasterIdx] - let slideLayoutIdx = page.extInfo.slideLayoutIdx - let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null - await drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) - await drawSlideMaster(slideMaster, slideLayout, placeholder) - if (slideLayout) { - await drawSlideLayout(slideLayout, placeholder) - } - } else { - await drawBackground(page.extInfo.background) - } - if (!page.children) { - return - } - recursion(page.children, obj => { - idMap[obj.id] = obj - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - // 继承母版占位符 - let element_property = obj.extInfo.property - let placeholder_property = placeholder[element_property.placeholder.type] || {} - for (let k in placeholder_property) { - if (element_property[k] == null) { - element_property[k] = placeholder_property[k] - } - } - } - }) - for (let i = 0; i < page.children.length; i++) { - await drawElement(page.children[i]) - } - recursion(page.children, obj => { - idMap[obj.id] = obj - }) - } - - this.getCanvas = () => { - return canvas - } - - this.resetSize = (width, height) => { - canvas.width = width * 2 - canvas.height = height * 2 - canvas.style.width = width + 'px' - canvas.style.height = height + 'px' - if (pptx) { - this.drawPptx(pptx, pageIndex) - } - } - - async function drawElement(obj) { - ctx.fillStyle = 'transparent' - ctx.strokeStyle = 'transparent' - if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { - // console.log('ignore element:', obj) - return - } - if (obj.type == 'text' || obj.type == 'freeform') { - await drawText(obj) - } else if (obj.type == 'image') { - await drawImage(obj) - } else if (obj.type == 'diagram') { - await drawDiagram(obj) - } else if (obj.type == 'container') { - await drawContainer(obj) - } else if (obj.type == 'table') { - await drawTable(obj) - } else if (obj.type == 'connector') { - await drawConnector(obj) - } else if (obj.type == 'graphicFrame') { - await drawGraphicFrame(obj) - } - } - - async function drawText(obj) { - let property = obj.extInfo.property - let geometryName = (property.geometry || {}).name || 'rect' - ctx.save() - shapeHandle(property) - let marginTop = property.strokeStyle ? (property.strokeStyle.lineWidth || 1) : 0 - if (geometryName == 'tableColumn') { - await drawTableColumn(property) - } else { - await drawGeometry(property) - } - let anchor = property.anchor - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - let x = ctx.groupFlipX || 1 - let y = ctx.groupFlipY || 1 - if (property.flipHorizontal) { - x *= -1 - } - if (property.flipVertical) { - y *= -1 - } - if (y == -1) { - if (x == 1) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - } - } else if (x == -1) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - } - if (templateHandle) { - await templateHandle('text', obj, ctx) - } - if (obj.children) { - let textInsets = property.textInsets || [0, 0, 0, 0] - let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 - let verticalAlignment = property.textVerticalAlignment - if (!isVertical && (verticalAlignment == 'MIDDLE' || verticalAlignment == 'BOTTOM')) { - let totalTextHeight = calcTextHeight(obj) - if (totalTextHeight < property.anchor[3]) { - if (verticalAlignment == 'MIDDLE') { - marginTop += (property.anchor[3] - totalTextHeight - textInsets[0] - textInsets[2]) / 2 + textInsets[0] - } else if (verticalAlignment == 'BOTTOM') { - marginTop += (property.anchor[3] - totalTextHeight - textInsets[2]) - } - } - } else { - marginTop += textInsets[0] - } - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - if (isVertical) { - await drawTextP(obj, p, isVertical, 0, i) - } else { - marginTop += await drawTextP(obj, p, isVertical, marginTop, i) - } - } - } - ctx.restore() - } - - function calcTextHeight(obj) { - let totalTextHeight = 0 - let wordWrap = obj.extInfo.property.textWordWrap ?? true - let textInsets = obj.extInfo.property.textInsets || [0, 0, 0, 0] - let wInset = textInsets[1] + textInsets[3] - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) - let maxFontSize = 0 - let underlined = false - let totalTextWidth = 0 - for (let j = 0; j < p.children.length; j++) { - let r_property = p.children[j].extInfo.property - let fontSize = r_property.fontSize || 16 - let text = p.children[j].text - if (text == '\n') { - totalTextHeight += lineSpacing * fontSize - continue - } - if (fontSize > maxFontSize) { - maxFontSize = fontSize - } - if (r_property.underlined) { - underlined = true - } - let fonts = [] - if (r_property.bold) { - fonts.push('bold') - } - if (r_property.italic) { - fonts.push('italic') - } - fonts.push(fontSize + 'px') - fonts.push('"' + (r_property.fontFamily || '等线') + '"') - ctx.font = fonts.join(' ') - let lines = text.split('\n') - let maxTextWidth = 0 - for (let s = 0; s < lines.length; s++) { - let width = ctx.measureText(lines[s]).width - if (width > maxTextWidth) { - maxTextWidth = width - } - } - totalTextWidth += maxTextWidth - if (lines.length > 1) { - totalTextHeight += (lines.length - 1) * lineSpacing * fontSize - } - } - if (wordWrap) { - let lineNum = parseInt((totalTextWidth - 1) / (obj.extInfo.property.anchor[2] - wInset)) + 1 - totalTextHeight += lineNum * lineSpacing * maxFontSize - } else { - totalTextHeight += lineSpacing * maxFontSize - } - if (underlined) { - totalTextHeight += 1 - } - } - return totalTextHeight - } - - async function drawTextP(textObj, p, isVertical, marginTop, pIdx) { - if (!p.children) { - return - } - let fontList = [] - let underlined = false - let totalTextWidth = 0 - let anchor = textObj.extInfo.property.anchor - let wordWrap = textObj.extInfo.property.textWordWrap ?? true - for (let i = 0; i < p.children.length; i++) { - let r = p.children[i] - let property = r.extInfo.property - let fontSize = property.fontSize || 16 - let fonts = [] - if (property.bold) { - fonts.push('bold') - } - if (property.italic) { - fonts.push('italic') - } - if (property.slideNum) { - r.text = (pageIndex + 1) + '' - } - fonts.push(fontSize + 'px') - fonts.push('"' + (property.fontFamily || '等线') + '"') - let font = fonts.join(' ') - fontList.push(font) - ctx.font = font - if (isVertical) { - if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { - if (fontSize > totalTextWidth) { - totalTextWidth = fontSize - } - } else if (r.text.length > 0) { - let width = ctx.measureText(r.text[0]).width - if (width > totalTextWidth) { - totalTextWidth = width - } - } - } else { - let lines = r.text.split('\n') - let maxTextWidth = 0 - for (let s = 0; s < lines.length; s++) { - let width = ctx.measureText(lines[s]).width - if (width > maxTextWidth) { - maxTextWidth = width - } - } - totalTextWidth += maxTextWidth - } - if (property.underlined) { - underlined = true - } - } - if (wordWrap) { - totalTextWidth = Math.min(totalTextWidth, anchor[2]) - } - let textAlign = p.extInfo.property.textAlign - let verticalAlignment = textObj.extInfo.property.textVerticalAlignment - let textInsets = textObj.extInfo.property.textInsets || [0, 0, 0, 0] - let lineSpacing = p.extInfo.property.lineSpacing > 0 ? (p.extInfo.property.lineSpacing / 100) : (1 + Math.abs(p.extInfo.property.lineSpacing || 0) / 100) - let x = anchor[0] - let y = anchor[1] + (marginTop || 0) - let endX = anchor[0] + anchor[2] - textInsets[3] - ctx.textAlign = 'left' - ctx.textBaseline = 'top' - if (textAlign == 'CENTER') { - x = x + (anchor[2] - totalTextWidth - textInsets[1] - textInsets[3]) / 2 + textInsets[1] - } else if (textAlign == 'RIGHT') { - x = x + anchor[2] - textInsets[3] - totalTextWidth - } else { - x = x + textInsets[1] - } - const _x = x - const _y = y - let lastWord = null - let maxFontSize = 0 - for (let i = 0; i < p.children.length; i++) { - let r = p.children[i] - let property = r.extInfo.property - let fontSize = property.fontSize || 16 - let drawString = (s, x, y) => { - doShadow(ctx, property.shadow) - ctx.translate(x, y) - ctx.fillText(s, 0, 0) - ctx.translate(-x, -y) - } - let fillStyle = await toPaint(property.fontColor, anchor) - ctx.fillStyle = fillStyle - if (property.line && (property.fontColor == null || property.fontColor.type == 'noFill')) { - drawString = (s, x, y) => { - doShadow(ctx, property.shadow) - ctx.translate(x, y) - ctx.strokeText(s, 0, 0) - ctx.translate(-x, -y) - } - ctx.strokeStyle = await toPaint(property.line.paint, anchor) - } - ctx.font = fontList[i] - if (fontSize > maxFontSize) { - maxFontSize = fontSize - } - if (r.text == '\n') { - y += lineSpacing * fontSize - x = _x - continue - } - if (isVertical) { - // 竖版 - x = x + fontSize * pIdx - if (property.lang == 'en-US' && /^[0-9a-zA-Z]+$/.test(r.text)) { - // 数字英文竖着的时候需要旋转90°方式呈现 - let textWidth = ctx.measureText(r.text).width - let fontSize = property.fontSize || 16 - ctx.save() - ctx.translate(x, y + fontSize) - ctx.rotate(90 * Math.PI / 180) - ctx.translate(-x, -y - fontSize) - drawString(r.text, x - fontSize, y) - ctx.restore() - y += textWidth - } else { - for (let j = 0; j < r.text.length; j++) { - let text = r.text[j] - drawString(text, x, y) - y += fontSize - } - } - if (property.underlined) { - let lineX = x - let lineY = _y - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX, lineY + (y - _y)) - ctx.closePath() - ctx.stroke() - } - } else if (wordWrap) { - // 横版-自动换行 - let texts = splitWords(r.text) - let drawLine = (textWidth) => { - if (property.underlined) { - let lineX = _x - let lineY = y - if (verticalAlignment == 'MIDDLE') { - lineY = lineY + fontSize / 2 + 1 - } else if (verticalAlignment == 'BOTTOM') { - lineY = lineY + 1 - } else { - lineY = lineY + fontSize + 1 - } - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX + textWidth, lineY) - ctx.closePath() - ctx.stroke() - } - } - for (let j = 0; j < texts.length; j++) { - let item = texts[j] - if (item.text == '\n') { - x = _x - y += lineSpacing * fontSize - lastWord = null - continue - } - if (item.word && lastWord != null && !lastWord) { - let textWidth = ctx.measureText(item.text).width - if (x + textWidth > endX + fontSize / 4) { - drawLine(x - _x) - x = _x - y += lineSpacing * fontSize - } - } - for (let s = 0; s < item.text.length; s++) { - let text = item.text[s] - let textWidth = ctx.measureText(text).width - if (x + textWidth > endX + fontSize / 4 && !isSymbol(text)) { - drawLine(x - _x) - x = _x - y += lineSpacing * fontSize - } - let ty = y - if (verticalAlignment == 'MIDDLE') { - ctx.textBaseline = 'middle' - ty = ty + (lineSpacing * fontSize) / 2 - } else if (verticalAlignment == 'BOTTOM') { - ctx.textBaseline = 'bottom' - ty = ty + (lineSpacing * fontSize) - } else { - ctx.textBaseline = 'top' - } - drawString(text, x, ty) - x += textWidth - } - lastWord = item.word - } - if (i == p.children.length - 1) { - drawLine(x - _x) - } - } else { - // 横版-不自动换行 - let lines = r.text.split('\n') - for (let s = 0; s < lines.length; s++) { - if (s != 0) { - x = _x - y += lineSpacing * fontSize - } - let ty = y - if (verticalAlignment == 'MIDDLE') { - ctx.textBaseline = 'middle' - ty = ty + (lineSpacing * fontSize) / 2 - } else if (verticalAlignment == 'BOTTOM') { - ctx.textBaseline = 'bottom' - ty = ty + (lineSpacing * fontSize) - } else { - ctx.textBaseline = 'top' - } - drawString(lines[s], x, ty) - let textWidth = ctx.measureText(lines[s]).width - if (property.underlined) { - let lineX = x - let lineY = y - if (verticalAlignment == 'MIDDLE') { - lineY = lineY + fontSize / 2 + 1 - } else if (verticalAlignment == 'BOTTOM') { - lineY = lineY + 1 - } else { - lineY = lineY + fontSize + 1 - } - ctx.lineWidth = 1 - ctx.strokeStyle = fillStyle - ctx.beginPath() - ctx.moveTo(lineX, lineY) - ctx.lineTo(lineX + textWidth, lineY) - ctx.closePath() - ctx.stroke() - } - x += textWidth - } - } - } - return (y - _y) + (underlined && !isVertical ? 1 : 0) + lineSpacing * maxFontSize - } - - async function drawImage(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - if (property.fillStyle && property.fillStyle.texture) { - property.fillStyle.texture.imageData = property.image - // 图片自带拉伸 - property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] - } else { - property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } - } - if (!property.geometry) { - property.geometry = { name: 'rect' } - } - await drawGeometry(property) - if (templateHandle) { - await templateHandle('image', obj, ctx) - } - ctx.restore() - } - - async function drawTableColumn(property) { - let anchor = property.anchor - let x = anchor[0] - 1 - let endX = anchor[0] + anchor[2] + 1 - let y = anchor[1] - 1 - let endY = anchor[1] + anchor[3] + 1 - let borders = property.borders // top/left/bottom/right - ctx.beginPath() - ctx.moveTo(x, y) - let top = borders[0] - ctx.strokeStyle = toColor({ color: top.color }, 'white') - ctx.lineWidth = top.lineWidth - ctx.lineTo(endX, y) - let right = borders[3] - ctx.strokeStyle = toColor({ color: right.color }, 'white') - ctx.lineWidth = right.lineWidth - ctx.lineTo(endX, endY) - let bottom = borders[2] - ctx.strokeStyle = toColor({ color: bottom.color }, 'white') - ctx.lineWidth = bottom.lineWidth - ctx.lineTo(x, endY) - let left = borders[1] - ctx.strokeStyle = toColor({ color: left.color }, 'white') - ctx.lineWidth = left.lineWidth - ctx.lineTo(x, anchor[1]) - ctx.closePath() - ctx.fillStyle = await toPaint(property.fillStyle, property.anchor) - ctx.fill() - ctx.stroke() - } - - async function drawDiagram(obj) { - let property = obj.extInfo.property - ctx.save() - ctx.translate(property.anchor[0], property.anchor[1]) - if (templateHandle) { - await templateHandle('diagram', obj, ctx) - } - for (let i = 0; i < obj.children.length; i++) { - await drawElement(obj.children[i]) - } - ctx.translate(-property.anchor[0], -property.anchor[1]) - ctx.restore() - } - - async function drawContainer(obj) { - let property = obj.extInfo.property - if (property.realType == 'Group') { - ctx.save() - let _groupFlipX = ctx.groupFlipX - let _groupFlipY = ctx.groupFlipY - let _groupRotation = ctx.groupRotation - if (templateHandle) { - await templateHandle('container', obj, ctx) - } - shapeHandle(property) - let parentGroupFillStyle = ctx.groupFillStyle - let groupFillStyle = property.groupFillStyle - if (groupFillStyle) { - groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) - groupFillStyle.groupAnchor = property.anchor - if (parentGroupFillStyle) { - groupFillStyle.parentGroupFillStyle = parentGroupFillStyle - } - } - ctx.groupFillStyle = groupFillStyle - let copyChildren = JSON.parse(JSON.stringify(obj.children)) - recursionGroupChildren(copyChildren, c => { - if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { - let anchor = c.extInfo.property.anchor - anchor[0] *= ctx.interior.scaleX - anchor[1] *= ctx.interior.scaleY - anchor[2] *= ctx.interior.scaleX - anchor[3] *= ctx.interior.scaleY - } - }) - for (let i = 0; i < copyChildren.length; i++) { - await drawElement(copyChildren[i]) - } - ctx.interior = ctx._interior - ctx.groupFlipX = _groupFlipX - ctx.groupFlipY = _groupFlipY - ctx.groupRotation = _groupRotation - ctx.restore() - } else { - for (let i = 0; i < obj.children.length; i++) { - await drawElement(obj.children[i]) - } - } - } - - function recursionGroupChildren(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.extInfo && c.extInfo.property.realType == 'Group') { - continue - } - if (c.children && c.children.length > 0) { - recursionGroupChildren(c.children, fn) - } - } - } - - async function drawConnector(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - await drawGeometry(property) - if (templateHandle) { - await templateHandle('connector', obj, ctx) - } - ctx.restore() - } - - async function drawGraphicFrame(obj) { - let property = obj.extInfo.property - ctx.save() - shapeHandle(property) - if (templateHandle) { - await templateHandle('graphicFrame', obj, ctx) - } - if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { - await drawChart(property.chart, property.anchor, canvas, ctx) - } - ctx.restore() - } - - async function drawTable(obj) { - let property = obj.extInfo.property - for (let i = 0; i < obj.children.length; i++) { - let row = obj.children[i] - await drawTableRow(obj, row) - } - } - - async function drawTableRow(table, row) { - let property = row.extInfo.property - for (let i = 0; i < row.children.length; i++) { - let column = row.children[i] - await drawText(column) - } - } - - async function drawGeometry(property) { - let geometry = property.geometry - let anchor = property.anchor - if (!geometry || !anchor || (anchor[2] == 0 && anchor[3] == 0)) { - return - } - ctx.save() - ctx.translate(anchor[0], anchor[1]) - let paths = geometryPaths(property) - let _anchor = [0, 0, anchor[2], anchor[3]] - if (geometry.name == 'custom') { - await drawPaths(paths, property, _anchor, anchor) - } else if (geometry.name == 'line' || geometry.name == 'straightConnector1') { - await drawPaths(paths, property, _anchor, anchor) - } else { - await drawPaths(paths, property, _anchor, anchor) - } - ctx.translate(-anchor[0], -anchor[1]) - ctx.restore() - } - - async function drawPaths(paths, property, anchor, real_anchor) { - for (let i = 0; i < paths.length; i++) { - let path = paths[i] - // console.log('path: ', path) - ctx.save() - let scaleX = path.scaleX - let scaleY = path.scaleY - ctx.scale(scaleX, scaleY) - let _anchor = [anchor[0], anchor[1], anchor[2], anchor[3]] - if (scaleX != 1 || scaleY != 1) { - _anchor[0] = _anchor[0] / scaleX - _anchor[1] = _anchor[1] / scaleY - _anchor[2] = _anchor[2] / scaleX - _anchor[3] = _anchor[3] / scaleY - } - ctx.beginPath() - let split = path.path.replace(/\s+/g, ' ').trim().split(' ') - for (let j = 0; j < split.length; j++) { - switch (split[j]) { - case 'M': - ctx.moveTo(split[++j], split[++j]) - break - case 'L': - ctx.lineTo(split[++j], split[++j]) - break - case 'Q': - ctx.quadraticCurveTo(split[++j], split[++j], split[++j], split[++j]) - break - case 'C': - ctx.bezierCurveTo(split[++j], split[++j], split[++j], split[++j], split[++j], split[++j]) - break - case 'Z': - ctx.closePath() - break - } - } - let strokeStyle = null - if (property.strokeStyle) { - ctx.lineWidth = (property.strokeStyle.lineWidth || 1) / scaleY - let lineCap = property.strokeStyle.lineCap - if (!lineCap || lineCap == 'FLAT') { - lineCap = 'butt' - } - ctx.lineCap = lineCap.toLowerCase() - strokeStyle = await toPaint(property.strokeStyle.paint, _anchor) - } - doShadow(ctx, property.shadow) - if (path.stroked && strokeStyle) { - ctx.strokeStyle = strokeStyle - } else { - ctx.strokeStyle = 'transparent' - } - ctx.stroke() - ctx.scale(1 / scaleX, 1 / scaleY) - let fillStyle = await toPaint(property.fillStyle, anchor) - if (path.filled) { - ctx.fillStyle = fillStyle - } else { - ctx.fillStyle = 'transparent' - } - if (property.fillStyle && property.fillStyle.type == 'bgFill') { - let rotation = (property.rotation || 0) + (ctx.groupRotation || 0) - if (rotation) { - ctx.translate(real_anchor[2] / 2, real_anchor[3] / 2) - ctx.rotate(-rotation * Math.PI / 180) - ctx.translate(-real_anchor[2] / 2, -real_anchor[3] / 2) - } - let tx = 0, ty = 0 - if (ctx.interior) { - tx = -ctx.interior.tx - real_anchor[0] - ty = -ctx.interior.ty - real_anchor[1] - } else { - tx = -real_anchor[0] - ty = -real_anchor[1] - } - ctx.translate(tx, ty) - ctx.fill() - ctx.translate(-tx, -ty) - } else { - ctx.fill() - } - ctx.restore() - } - } - - function shapeHandle(property) { - let anchor = property.anchor - if (!anchor) { - return - } - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - if (property.rotation) { - // 旋转 - ctx.translate(cx, cy) - ctx.rotate(property.rotation * Math.PI / 180) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation - } - } - if (property.flipVertical) { - ctx.translate(cx, cy) - ctx.scale(1, -1) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupFlipY = -(ctx.groupFlipY || 1) - } - } - if (property.flipHorizontal) { - ctx.translate(cx, cy) - ctx.scale(-1, 1) - ctx.translate(-cx, -cy) - if (property.realType == 'Group') { - ctx.groupFlipX = -(ctx.groupFlipX || 1) - } - } - // 嵌套容器 Group - let interior = property.interiorAnchor - if (interior && interior.length > 0) { - /* - // 缩放 - let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] - let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] - ctx.scale(scaleX, scaleY) - ctx.translate(anchor[0] / scaleX - interior[0], anchor[1] / scaleY - interior[1]) - */ - let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] - let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] - let tx = anchor[0] - interior[0] * scaleX - let ty = anchor[1] - interior[1] * scaleY - ctx.translate(tx, ty) - ctx._interior = ctx.interior - ctx.interior = { scaleX, scaleY, tx, ty } - } else if (property.realType == 'Group') { - ctx._interior = ctx.interior - ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } - } - } - - async function drawBackground(background) { - if (!background) { - ctx.bgFillStyle = null - return - } - ctx.fillStyle = await toPaint(background.fillStyle, background.anchor, true) - ctx.fillRect(background.anchor[0], background.anchor[1], background.anchor[2], background.anchor[3]) - ctx.bgFillStyle = ctx.fillStyle - } - - async function drawSlideMaster(slideMaster, slideLayout, placeholder) { - recursion(slideMaster.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - if (slideLayout && slideLayout.noMaster) { - return - } - for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { - await drawElement(slideMaster.children[i]) - } - } - - async function drawSlideLayout(slideLayout, placeholder) { - recursion(slideLayout.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { - await drawElement(slideLayout.children[i]) - } - } - - function recursion(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.children && c.children.length > 0) { - recursion(c.children, fn) - } - } - } - - function doShadow(ctx, shadow) { - if (!shadow) { - return - } - ctx.shadowBlur = shadow.blur || 0 - ctx.shadowColor = toColor(shadow.fillStyle.color) - if (shadow.distance) { - let radians = (shadow.angle || 0) * Math.PI / 180 - let x = 0, y = 0, r = shadow.distance * 2 - ctx.shadowOffsetX = x + r * Math.cos(radians) - ctx.shadowOffsetY = y + r * Math.sin(radians) - } - } - - function toPaint(paint, anchor, isBackground, defaultColor) { - return new Promise((resolve, reject) => { - if (!paint) { - resolve(defaultColor || 'transparent') - } else if (paint.type == 'noFill') { - // 无填充 - resolve('transparent') - } else if (paint.type == 'color') { - // 颜色 - resolve(toColor(paint.color, defaultColor)) - } else if (paint.type == 'bgFill') { - // 背景填充 - resolve(ctx.bgFillStyle || defaultColor || 'transparent') - } else if (paint.type == 'groupFill') { - // 组合背景 - let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle - if (groupFillStyle) { - toPaint(groupFillStyle, anchor || groupFillStyle.groupAnchor, false, defaultColor).then(res => { - resolve(res) - }) - } else { - resolve(defaultColor || 'transparent') - } - } else if (paint.type == 'gradient') { - // 渐变 - let gradient = paint.gradient - let x = anchor[0], y = anchor[1], width = anchor[2], height = anchor[3] - let centerX = x + width / 2 - let centerY = y + height / 2 - let gradientObj - // linear,circular,rectangular,shape - if (gradient.gradientType == 'circular') { - // 射线 - let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) - let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 - let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 - gradientObj = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius) - } else { - // 线性 - let startX = x - let startY = centerY - let endX = x + width - let endY = centerY - if (gradient.angle) { - let radians = gradient.angle * Math.PI / 180 - let midX = (startX + endX) / 2 - let midY = (startY + endY) / 2 - let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) - let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) - let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) - let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) - startX = newStartX - startY = newStartY - endX = newEndX - endY = newEndY - } - gradientObj = ctx.createLinearGradient(startX, startY, endX, endY) - } - for (let i = 0; i < gradient.colors.length; i++) { - let color = gradient.colors[i] - gradientObj.addColorStop(gradient.fractions[i], toColor(color)) - } - resolve(gradientObj) - } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { - resolve('transparent') - } else if (paint.type == 'texture') { - // 图片或纹理 - let texture = paint.texture - let anonymous = texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst - loadImage(texture.imageData, anonymous).then(img => { - if (img) { - let pat = createTexturePattern(img, texture, anchor, isBackground) - resolve(pat) - } else { - resolve('transparent') - } - }) - } else if (paint.type == 'pattern') { - // 图案 - let pattern = paint.pattern - // let prst = pattern.prst - let fgColor = pattern.fgColor.realColor - let bgColor = pattern.bgColor.realColor - let width = anchor[2], height = anchor[3] - let imgCanvas = document.createElement('canvas') - imgCanvas.width = width - imgCanvas.height = height - let imgCtx = imgCanvas.getContext('2d') - imgCtx.imageSmoothingEnabled = true - imgCtx.imageSmoothingQuality = 'high' - let imgData = imgCtx.createImageData(width, height) - let line = 0 - for (let i = 0; i < imgData.data.length; i += 4) { - if (++line % 16 == 0) { - // 前景 - imgData.data[i + 0] = (fgColor >> 16) & 255 - imgData.data[i + 1] = (fgColor >> 8) & 255 - imgData.data[i + 2] = (fgColor >> 0) & 255 - imgData.data[i + 3] = (fgColor >> 24) & 255 - } else { - // 背景 - imgData.data[i + 0] = (bgColor >> 16) & 255 - imgData.data[i + 1] = (bgColor >> 8) & 255 - imgData.data[i + 2] = (bgColor >> 0) & 255 - imgData.data[i + 3] = (bgColor >> 24) & 255 - } - if (i % 400 == 0) { - line += 2 - } - } - imgCtx.putImageData(imgData, 0, 0) - let imgSrc = imgCanvas.toDataURL() - let image = new Image() - image.src = imgSrc - image.onload = async function() { - resolve(ctx.createPattern(image, 'no-repeat')) - } - } - }) - } - - function createTexturePattern(img, texture, anchor, isBackground) { - let width = anchor[2] - let height = anchor[3] - let mode = texture.alignment || !texture.stretch ? 'repeat' : 'no-repeat' - if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { - return ctx.createPattern(img, mode) - } - if (texture.alignment || !texture.stretch) { - width = img.width - height = img.height - } - let patternCanvas = document.createElement('canvas') - patternCanvas.width = Math.max(1, width) - patternCanvas.height = Math.max(1, height) - let patternCtx = patternCanvas.getContext('2d') - patternCtx.imageSmoothingEnabled = true - patternCtx.imageSmoothingQuality = 'high' - if (texture.alpha >= 0 && texture.alpha < 100000) { - patternCtx.globalAlpha = texture.alpha / 100000 - } - let imgInsets = null - if (texture.insets) { - let top = texture.insets[0] / 100000 - let left = texture.insets[1] / 100000 - let bottom = texture.insets[2] / 100000 - let right = texture.insets[3] / 100000 - let x = img.width * left - let y = img.height * top - let w = img.width * (1 - left - right) - let h = img.height * (1 - top - bottom) - imgInsets = [x, y, w, h] - } - if (texture.stretch) { - let top = texture.stretch[0] / 100000 - let left = texture.stretch[1] / 100000 - let bottom = texture.stretch[2] / 100000 - let right = texture.stretch[3] / 100000 - let x = width * left - let y = height * top - let w = width * (1 - left - right) - let h = height * (1 - top - bottom) - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) - } else { - patternCtx.drawImage(img, x, y, w, h) - } - } else if (texture.alignment) { - let x = 0, y = 0 - if (texture.alignment == 'CENTER') { - if (width > anchor[2]) { - x = (width - anchor[2]) / 2 - } - if (height > anchor[3]) { - y = (height - anchor[3]) / 2 - } - } - patternCtx.drawImage(img, x, y, width, height, 0, 0, width, height) - } else { - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) - } else { - patternCtx.drawImage(img, 0, 0, width, height) - } - } - if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { - try { - // 重新着色 - let color = texture.duoTone[0].realColor - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) - let data = imageData.data - for(var i = 0; i < data.length; i += 4) { - let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 - // black / white - let prst = texture.duoTonePrst == 'white' ? 255 : 0 - data[i] = gray * r + (1 - gray) * prst - data[i + 1] = gray * g + (1 - gray) * prst - data[i + 2] = gray * b + (1 - gray) * prst - } - patternCtx.putImageData(imageData, 0, 0) - } catch(e) { /* empty */ } - } - return ctx.createPattern(patternCanvas, mode) - } - - function toColor(colorObj, defaultColor) { - if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { - return defaultColor || 'transparent' - } - let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let a = ((color >> 24) & 255) / 255 - if (colorObj.realColor == null) { - if (colorObj.alpha != null && colorObj.alpha != -1) { - if (colorObj.alpha > 1000) { - a = colorObj.alpha / 100000 - } else { - a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 - } - a = Math.min(1, Math.max(0, a)) - } - if (colorObj.lumMod && colorObj.lumMod > 0) { - let value = colorObj.lumMod / 100000 - r = r * value - g = g * value - b = b * value - } - if (colorObj.lumOff && colorObj.lumOff > 0) { - let value = colorObj.lumOff / 100000 - r += 255 * value - g += 255 * value - b += 255 * value - } - } - return `rgba(${r}, ${g}, ${b}, ${a})` - } - - function toColorValue(r, g, b, a) { - a = (a == null ? 255 : a) - return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 - } - - function loadImage(src, anonymous) { - return new Promise(resolve => { - if (!src) { - resolve() - return - } - let cacheKey - if (src.length < 15) { - cacheKey = src - } else { - cacheKey = src.length + '_' + src.substring(src.length - 15) - } - let img = imageCache[cacheKey] - if (img == null) { - img = new Image() - if (imageCrossOrigin || anonymous) { - let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) - if (!eqOrigin) { - // anonymous / use-credentials - img.crossOrigin = imageCrossOrigin || 'anonymous' - } - } - img.src = src - img.onload = function() { - imageCache[cacheKey] = img - resolve(img) - } - img.onerror = function (e) { - resolve() - console.log('图片加载失败: ', src, e) - } - } else { - resolve(img) - } - }) - } - - function value2px(v, isEmu) { - if (isEmu) { - return +v / 12700 - } else { - return +v - } - } - - function value2emu(v) { - return +v * 12700 - } - - function getTfx(x, div) { - if (div) { - return x / (ctx.getTransform().a / ctx.scaleX) - } else { - return x * (ctx.getTransform().a / ctx.scaleX) - } - } - - function getTfy(y, div) { - if (div) { - return y / (ctx.getTransform().d / ctx.scaleY) - } else { - return y * (ctx.getTransform().d / ctx.scaleY) - } - } - - function splitWords(str) { - if (!str) { - return [] - } - let pattern = /^[0-9a-zA-Z]+$/ - let array = [] - let item = '' - let math = null - for (let i = 0; i < str.length; i++) { - if (str[i] == '\n') { - if (item) { - array.push({ text: item, word: math }) - } - array.push({ text: '\n', word: false }) - item = '' - math = null - } else { - let _math = pattern.test(str[i]) - if (math == null) { - math = _math - item += str[i] - } else if (_math == math) { - item += str[i] - } else { - array.push({ text: item, word: math }) - item = str[i] - math = _math - } - } - } - if (item) { - array.push({ text: item, word: math }) - } - return array - } - - function isSymbol(s) { - switch (s) { - case ',': - case '.': - case '!': - case '?': - case ')': - case ';': - case ',': - case '。': - case '!': - case '?': - case ')': - case ';': - case '”': - case ' ': - return true - } - return false - } - - function rgb2hsv(r, g, b) { - r /= 255, g /= 255, b /= 255 - let max = Math.max(r, g, b), min = Math.min(r, g, b) - let h, s, v = max - let d = max - min - s = max == 0 ? 0 : d / max - if (max == min) { - h = 0 - } else { - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break - case g: h = (b - r) / d + 2; break - case b: h = (r - g) / d + 4; break - } - h /= 6 - } - return [h, s, v] - } - - function hsv2rgb(h, s, v) { - let r, g, b - let i = Math.floor(h * 6) - let f = h * 6 - i - let p = v * (1 - s) - let q = v * (1 - f * s) - let t = v * (1 - (1 - f) * s) - switch (i % 6) { - case 0: r = v, g = t, b = p; break - case 1: r = q, g = v, b = p; break - case 2: r = p, g = v, b = t; break - case 3: r = p, g = q, b = v; break - case 4: r = t, g = p, b = v; break - case 5: r = v, g = p, b = q; break - } - return [r * 255, g * 255, b * 255] - } - - function text(obj) { - if (obj == null) { - return null - } - let text = obj.text - if (text != null) { - return text - } - if (obj.children != null && obj.children.length > 0) { - let textAll = '' - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - if (p.children == null) { - continue - } - let pText = '' - for (let j = 0; j < p.children.length; j++) { - let r = p.children[j] - if (r.text == null) { - continue - } - pText += r.text - } - if (pText) { - textAll += (pText + '\n') - } - } - if (textAll.length > 0) { - textAll = textAll.substring(0, textAll.length - 1) - } - return textAll - } - return '' - } - - this.setTemplateHandle = (_templateHandle) => { - templateHandle = _templateHandle - } - - this.idMap = idMap - this.recursion = recursion - this.drawGeometry = drawGeometry - this.drawElement = drawElement - this.toPaint = toPaint - this.toColor = toColor - this.toColorValue = toColorValue - this.loadImage = loadImage - this.text = text - -} - -export { Ppt2Canvas } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js deleted file mode 100644 index 3ff7443..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/ppt2svg.js +++ /dev/null @@ -1,2265 +0,0 @@ -/* eslint-disable no-unused-vars */ -import { geometryPaths } from './geometry.js' -import { drawChart } from './chart.js' - -function D3Element(element) { - this.attr = function (k, v) { - if (v == undefined) { - return element.getAttribute(k) - } else { - element.setAttribute(k, v) - return this - } - } - this.style = function (k, v) { - if (v == undefined) { - return element.style[k] - } else { - element.style[k] = v - return this - } - } - this.text = function (v) { - if (v == undefined) { - return element.textContent - } else { - element.textContent = v - return this - } - } - this.append = function (tag) { - let node = document.createElementNS('http://www.w3.org/2000/svg', tag) - element.appendChild(node) - return new D3Element(node) - } - this.parent = function () { - return element.parentNode ? new D3Element(element.parentNode) : null - } - this.node = function () { - return element - } - this.html = function (v) { - if (v == undefined) { - return element.innerHTML - } else { - element.innerHTML = v - return this - } - } - this.translate = function (x, y, start) { - let transform = element.getAttribute('transform') - if (x == undefined && y == undefined) { - x = y = 0 - if (transform) { - let idx = transform.indexOf('translate') - if (idx > -1) { - let arr = transform.substring(idx + 10, transform.indexOf(')', idx + 10)).replace('(', '').split(',') - x = parseFloat(arr[0] || 0) - y = parseFloat(arr[1] || 0) - } - } - return { x, y } - } else { - if (y == undefined) { - y = 0 - } - if (transform) { - let idx = transform.indexOf('translate') - if (idx > -1) { - let eIdx = transform.indexOf(')', idx + 10) - transform = transform.substring(0, idx) + `translate(${x}, ${y})` + transform.substring(eIdx + 1) - element.setAttribute('transform', transform.trim()) - } else { - element.setAttribute('transform', start ? `translate(${x}, ${y}) ${transform}`: `${transform} translate(${x}, ${y})`) - } - } else { - element.setAttribute('transform', `translate(${x}, ${y})`) - } - return this - } - } - this.scale = function (x, y, start) { - let transform = element.getAttribute('transform') - if (x == undefined && y == undefined) { - x = y = 1 - if (transform) { - let idx = transform.indexOf('scale') - if (idx > -1) { - let arr = transform.substring(idx + 6, transform.indexOf(')', idx + 6)).replace('(', '').split(',') - x = parseFloat(arr[0] || 0) - y = arr[1] == undefined ? x : parseFloat(arr[1]) - } - } - return { x, y } - } else { - if (y == undefined) { - y = x - } - if (transform) { - let idx = transform.indexOf('scale') - if (idx > -1) { - let eIdx = transform.indexOf(')', idx + 6) - transform = transform.substring(0, idx) + `scale(${x}, ${y})` + transform.substring(eIdx + 1) - element.setAttribute('transform', transform.trim()) - } else { - element.setAttribute('transform', start ? `scale(${x}, ${y}) ${transform}` : `${transform} scale(${x}, ${y})`) - } - } else { - element.setAttribute('transform', `scale(${x}, ${y})`) - } - return this - } - } - this.rotate = function (rotate, x, y, start) { - let transform = element.getAttribute('transform') - if (rotate == undefined) { - x = y = 0 - if (transform) { - let idx = transform.indexOf('rotate') - if (idx > -1) { - let arr = transform.substring(idx + 7, transform.indexOf(')', idx + 7)).replace('(', '').split(',') - rotate = parseFloat(arr[0] || 0) - x = arr[1] == undefined ? 0 : parseFloat(arr[1]) - y = arr[2] == undefined ? 0 : parseFloat(arr[2]) - } - } - return { rotate, x, y } - } else { - let transformRotate = rotate ? `rotate(${rotate})` : '' - if (x != undefined && y != undefined) { - transformRotate = `rotate(${rotate}, ${x}, ${y})` - } - if (transform) { - let idx = transform.indexOf('rotate') - if (idx > -1) { - let eIdx = transform.indexOf(')', idx + 7) - transform = transform.substring(0, idx) + transformRotate + transform.substring(eIdx + 1) - element.setAttribute('transform', transform.trim()) - } else { - element.setAttribute('transform', start ? `${transformRotate} ${transform}` : `${transform} ${transformRotate}`) - } - } else { - element.setAttribute('transform', transformRotate) - } - return this - } - } -} - -const d3 = { - select: function (o) { - return new D3Element((typeof o == 'string') ? document.querySelector(o) : o) - }, - addEventListener: function (type, event, fun) { - if (type === 'window') { - window.addEventListener(event, fun) - } else if (type === 'document') { - document.addEventListener(event, fun) - } - } -} - -function Ppt2Svg(_svg, svgWidth, svgHeight) { - var pptx = null - var page = null - var imageCache = {} - var pageIndex = 0 - var ctx = {} - var idMap = {} - var counter = 0 - var zoom = 1 - var defs = null - var mode = 'view' - var pointList = [] - var mTimer = null - var currentPoint = null - var currentSelect = null - // eslint-disable-next-line @typescript-eslint/no-this-alias - const $this = this - const svg = d3.select((typeof _svg == 'string') ? ('#' + _svg) : _svg) - .attr('width', svgWidth || 960) - .attr('height', svgHeight || 540) - - this.drawPptx = (pptxObj, pageIdx, selectElementId) => { - removePoint() - removeElementMoveScale() - ctx = {} - idMap = {} - imageCache = {} - counter = 0 - pptx = pptxObj - pageIndex = pageIdx - zoom = svgWidth / pptx.width - svg.html('') - defs = svg.append('defs') - page = pptxObj.pages[pageIdx] - let placeholder = {} - let slideMasterIdx = page.extInfo.slideMasterIdx - if (slideMasterIdx != null && pptxObj.slideMasters) { - let slideMaster = pptxObj.slideMasters[slideMasterIdx] - let slideLayoutIdx = page.extInfo.slideLayoutIdx - let slideLayout = slideLayoutIdx != null ? slideMaster.slideLayouts[slideLayoutIdx] : null - drawBackground(page.extInfo.background || (slideLayout || {}).background || slideMaster.background) - drawSlideMaster(slideMaster, slideLayout, placeholder) - if (slideLayout) { - drawSlideLayout(slideLayout, placeholder) - } - } else { - drawBackground(page.extInfo.background) - } - if (!page.children) { - return - } - recursion(page.children, obj => { - idMap[obj.id] = obj - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - // 继承母版占位符 - let element_property = obj.extInfo.property - let placeholder_property = placeholder[element_property.placeholder.type] || {} - for (let k in placeholder_property) { - if (element_property[k] == null) { - element_property[k] = placeholder_property[k] - } - } - } - }) - for (let i = 0; i < page.children.length; i++) { - drawElement(page.children[i]) - } - recursion(page.children, obj => { - idMap[obj.id] = obj - }) - calcPointList(page) - if (selectElementId) { - addElementMoveScale(idMap[selectElementId]) - } - } - - this.svgNode = () => { - return svg.node() - } - - this.resetSize = (_svgWidth, _svgHeight) => { - svgWidth = _svgWidth || svgWidth - svgHeight = _svgHeight || svgHeight - svg.attr('width', svgWidth).attr('height', svgHeight) - if (pptx) { - zoom = svgWidth / pptx.width - this.drawPptx(pptx, pageIndex) - } - } - - this.setMode = (_mode) => { - // view / edit - mode = _mode || 'view' - return mode - } - - function scaleAnchor(point) { - return point ? [...point.map(s => s * zoom)] : point - } - - function scaleValue(value) { - return value ? value * zoom : value - } - - function shapeHandle(property, parent) { - let g = parent.append('g') - let anchor = scaleAnchor(property.anchor) - if (!anchor) { - g.attr('groupFlipX', ctx.groupFlipX || 1) - g.attr('groupFlipY', ctx.groupFlipY || 1) - return g - } - let transform = [] - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - transform.push(`rotate(${property.rotation || 0}, ${cx}, ${cy})`) - if (property.rotation) { - if (property.realType == 'Group') { - ctx.groupRotation = (ctx.groupRotation || 0) + property.rotation - } - } - if (property.flipVertical) { - transform.push(`translate(${cx}, ${cy})`) - transform.push(`scale(1, -1)`) - transform.push(`translate(${-cx}, ${-cy})`) - if (property.realType == 'Group') { - ctx.groupFlipY = -(ctx.groupFlipY || 1) - } - } - if (property.flipHorizontal) { - transform.push(`translate(${cx}, ${cy})`) - transform.push(`scale(-1, 1)`) - transform.push(`translate(${-cx}, ${-cy})`) - if (property.realType == 'Group') { - ctx.groupFlipX = -(ctx.groupFlipX || 1) - } - } - // 嵌套容器 Group - let interior = scaleAnchor(property.interiorAnchor) - if (interior && interior.length > 0) { - let scaleX = interior[2] == 0 || anchor[2] == interior[2] ? 1 : anchor[2] / interior[2] - let scaleY = interior[3] == 0 || anchor[3] == interior[3] ? 1 : anchor[3] / interior[3] - let tx = anchor[0] - interior[0] * scaleX - let ty = anchor[1] - interior[1] * scaleY - transform.push(`translate(${tx}, ${ty})`) - ctx._interior = ctx.interior - ctx.interior = { scaleX, scaleY, tx, ty } - } else if (property.realType == 'Group') { - ctx._interior = ctx.interior - ctx.interior = { scaleX: 1, scaleY: 1, tx: 0, ty: 0 } - } else if (ctx.interior) { - g.attr('interior', JSON.stringify(ctx.interior)) - } - if (transform.length > 0) { - g.attr('transform', transform.join(' ')) - } - g.attr('groupFlipX', ctx.groupFlipX || 1) - g.attr('groupFlipY', ctx.groupFlipY || 1) - return g - } - - function drawBackground(background) { - if (!background) { - ctx.bgAnchor = null - ctx.bgFillStyle = null - return - } - let anchor = scaleAnchor(background.anchor) - ctx.bgAnchor = anchor - ctx.bgFillStyle = background.fillStyle - let fill = toPaint(background.fillStyle, anchor) - svg.append('rect') - .attr('x', 0).attr('y', 0) - .attr('width', anchor[2]) - .attr('height', anchor[3]) - .attr('fill', fill) - .node().addEventListener('click', function (e) { - if (!currentPoint) { - removeElementMoveScale() - } - }) - } - - function drawSlideMaster(slideMaster, slideLayout, placeholder) { - recursion(slideMaster.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - if (slideLayout && slideLayout.noMaster) { - return - } - for (let i = 0; slideMaster.children && i < slideMaster.children.length; i++) { - drawElement(slideMaster.children[i]) - } - } - - function drawSlideLayout(slideLayout, placeholder) { - recursion(slideLayout.children, obj => { - if (obj.extInfo.property && obj.extInfo.property.placeholder) { - obj.noDraw = true - placeholder[obj.extInfo.property.placeholder.type] = obj.extInfo.property - } - }) - for (let i = 0; slideLayout.children && i < slideLayout.children.length; i++) { - drawElement(slideLayout.children[i]) - } - } - - function recursion(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.children && c.children.length > 0) { - recursion(c.children, fn) - } - } - } - - function drawElement(obj, parent) { - if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { - // console.log('ignore element:', obj) - return - } - if (!parent) { - parent = svg - } - if (obj.type == 'text' || obj.type == 'freeform') { - drawText(obj, parent) - } else if (obj.type == 'image') { - drawImage(obj, parent) - } else if (obj.type == 'diagram') { - drawDiagram(obj, parent) - } else if (obj.type == 'container') { - drawContainer(obj, parent) - } else if (obj.type == 'table') { - drawTable(obj, parent) - } else if (obj.type == 'connector') { - drawConnector(obj, parent) - } else if (obj.type == 'graphicFrame') { - drawGraphicFrame(obj, parent) - } - } - - this.redrawElementWithId = (id) => { - let obj = idMap[id] - if (obj.noDraw || !obj.extInfo.property.anchor || obj.extInfo.property.hidden) { - return - } - let parent = idMap[obj.pid] - while (parent) { - if (parent.type == 'container') { - // 重新渲染页面 - this.drawPptx(pptx, pageIndex, id) - return - } - parent = idMap[parent.pid] - } - let list = [] - if (obj.point) { - let x = obj.point[0] - let y = obj.point[1] - let endX = obj.point[0] + obj.point[2] - let endY = obj.point[1] + obj.point[3] - for (let i = 0; i < pointList.length; i++) { - let point = pointList[i] - if (point.obj.id == id) { - break - } - if (point.x >= x && point.y >= y && point.endX <= endX && point.endY <= endY) { - list.push(point.obj) - } else if (point.y > y && point.y < endY && (point.x > x && point.x < endX || point.endX > x && point.endX < endX)) { - list.push(point.obj) - } else if (point.x > x && point.x < endX && (point.y > y && point.y < endY || point.endY > y && point.endY < endY)) { - list.push(point.obj) - } - if (list.length > 0) { - // 重新渲染页面 - this.drawPptx(pptx, pageIndex, id) - return - } - } - } - let element = document.getElementById('g-' + obj.id) - if (element) { - element.remove() - let parent = element.parentNode ? d3.select(element.parentNode) : null - drawElement(obj, parent) - } - page && calcPointList(page) - if (currentSelect) { - addElementMoveScale(currentSelect) - } - } - - function drawText(obj, parent) { - let property = obj.extInfo.property - let geometryName = (property.geometry || {}).name || 'rect' - let g = shapeHandle(property, parent) - g.attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - if (geometryName == 'tableColumn') { - drawTableColumn(property, g) - } else { - drawGeometry(property, g) - } - if (!obj.children || obj.children.length == 0) { - return - } - drawTextWithG(g, obj) - } - - function drawTextWithG(g, obj) { - let childNodes = g.node().childNodes - for (let i = childNodes.length - 1; i >= 0; i--) { - if (childNodes[i].tagName == 'text') { - childNodes[i].remove() - } - } - if (!obj.children || obj.children.length == 0) { - return - } - let property = obj.extInfo.property - let anchor = scaleAnchor(property.anchor) - let wordWrap = property.textWordWrap ?? true - let textInsets = property.textInsets || [0, 0, 0, 0] - let isVertical = property.textDirection && property.textDirection.indexOf('VERTICAL') > -1 - let verticalAlignment = property.textVerticalAlignment - let textNode = g.append('text').attr('id', obj.id).attr('x', anchor[0]).attr('y', anchor[1]) - textNode.style('user-select', 'none') - if (isVertical) { - textNode.style('writing-mode', 'vertical-rl') - } - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - let x = parseInt(g.attr('groupFlipX') || ctx.groupFlipX || 1) - let y = parseInt(g.attr('groupFlipY') || ctx.groupFlipX || 1) - let transform = [] - if (property.flipHorizontal) { - x *= -1 - } - if (property.flipVertical) { - y *= -1 - } - if (y == -1) { - if (x == 1) { - transform.push(`translate(${cx}, ${cy})`) - transform.push(`scale(-1, 1)`) - transform.push(`translate(${-cx}, ${-cy})`) - } - } else if (x == -1) { - transform.push(`translate(${cx}, ${cy})`) - transform.push(`scale(-1, 1)`) - transform.push(`translate(${-cx}, ${-cy})`) - } - if (transform.length > 0) { - textNode.attr('transform', transform.join(' ')) - } - let marginTop = property.strokeStyle ? scaleValue(property.strokeStyle.lineWidth || 1) : 0 - let maxFontSize = 0 - let maxWidth = anchor[2] - textInsets[1] - textInsets[3] - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - let p_property = p.extInfo.property - let textAlign = p_property.textAlign - let lineSpacing = p_property.lineSpacing > 0 ? (p_property.lineSpacing / 100) : (1 + Math.abs(p_property.lineSpacing || 0) / 100) - let createPNode = () => { - let pNode = textNode.append('tspan').attr('id', p.id) - if (textAlign == 'CENTER') { - pNode.attr('x', anchor[0] + (anchor[2] - textInsets[1] - textInsets[3]) / 2 + textInsets[1]) - pNode.attr('text-anchor', 'middle') - } else if (textAlign == 'RIGHT') { - pNode.attr('x', anchor[0] + anchor[2] - textInsets[3]) - pNode.attr('text-anchor', 'end') - } else { - pNode.attr('x', anchor[0] + textInsets[1]) - pNode.attr('text-anchor', 'start') - } - return pNode - } - let pNode = createPNode() - for (let i = 0; i < p.children.length; i++) { - let r = p.children[i] - let r_property = r.extInfo.property - if (r_property.slideNum) { - r.text = (pageIndex + 1) + '' - } - let fontSize = scaleValue(r_property.fontSize || 16) - let createRNode = (_pNode) => { - let rNode = _pNode.append('tspan').attr('id', r.id) - if (r_property.bold) { - rNode.style('font-weight', 'bold') - } - if (r_property.italic) { - rNode.style('font-style', 'italic') - } - if (r_property.underlined) { - rNode.style('text-decoration', 'underline') - } - rNode.style('cursor', 'text') - rNode.style('font-size', fontSize + 'px') - rNode.style('font-family', (r_property.fontFamily || '等线')) - let filter = toShadow(r_property.shadow, anchor) - if (filter) { - rNode.attr('filter', filter) - } - if (r_property.line && (r_property.fontColor == null || r_property.fontColor.type == 'noFill')) { - let fillStyle = toPaint(r_property.line.paint, anchor) - rNode.attr('fill', 'none') - rNode.attr('stroke', fillStyle) - rNode.attr('stroke-width', scaleValue(r_property.line.lineWidth || 1)) - } else { - let params = {} - if (r_property.fontColor.type == 'texture') { - params.tx = anchor[0] - params.ty = anchor[1] + marginTop - } - let fillStyle = toPaint(r_property.fontColor, anchor, params) - rNode.attr('fill', fillStyle) - } - addRunTextEvent(rNode, obj) - return rNode - } - maxFontSize = Math.max(fontSize, maxFontSize) - let rNode = createRNode(pNode) - if (isVertical) { - // 竖版 - rNode.text(r.text) - } else { - // 横版 - rNode.text(r.text) - if (wordWrap && pNode.node().getComputedTextLength() > maxWidth && r.text.length > 1) { - // 自动换行 - let start = 0 - for (let s = 1; s <= r.text.length; s++) { - let text = r.text.substring(start, s) - rNode.text(text) - if (pNode.node().getComputedTextLength() > maxWidth - maxFontSize / 2) { - marginTop += (maxFontSize * lineSpacing) - pNode.attr('y', anchor[1] + marginTop) - pNode = createPNode() - rNode = createRNode(pNode) - start = s - } - } - } - } - } - if (isVertical) { - if (verticalAlignment == 'MIDDLE') { - pNode.attr('x', anchor[0] + maxFontSize * (obj.children.length - i - 1) + (anchor[2] - maxFontSize * obj.children.length) / 2) - } else if (verticalAlignment == 'TOP') { - pNode.attr('x', anchor[0] + anchor[2] - maxFontSize * (i + 1)) - } else { - pNode.attr('x', anchor[0] + maxFontSize * (obj.children.length - i - 1)) - } - pNode.attr('y', anchor[1]) - } else { - marginTop += (maxFontSize * lineSpacing) - pNode.attr('y', anchor[1] + marginTop) - } - } - let yHeight = 0 - if (verticalAlignment == 'MIDDLE') { - let height = textNode.node().getBBox().height - yHeight = (anchor[3] - height - textInsets[0] - textInsets[2]) / 2 + textInsets[0] - maxFontSize / 4 - } else if (verticalAlignment == 'BOTTOM') { - let height = textNode.node().getBBox().height - yHeight = anchor[3] - height - textInsets[2] - } - if (yHeight != 0) { - let childNodes = textNode.node().childNodes - for (let i = 0; i < childNodes.length; i++) { - let pNode = childNodes[i] - let y = +pNode.getAttribute('y') + yHeight - pNode.setAttribute('y', y) - } - } - } - - function drawImage(obj, parent) { - let property = obj.extInfo.property - let g = shapeHandle(property, parent) - g.attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - if (property.fillStyle && property.fillStyle.texture) { - property.fillStyle.texture.imageData = property.image - // 图片自带拉伸 - property.fillStyle.texture.stretch = property.fillStyle.texture.stretch || [0, 0, 0, 0] - } else { - property.fillStyle = { 'type': 'texture', texture: { 'imageData': property.image, insets: property.clipping, stretch: [0, 0, 0, 0] } } - } - drawGeometry(property, g, obj.id) - } - - function drawTableColumn(property, parent) { - let anchor = scaleAnchor(property.anchor) - let x = anchor[0] - 1 - let endX = anchor[0] + anchor[2] + 1 - let y = anchor[1] - 1 - let endY = anchor[1] + anchor[3] + 1 - let borders = scaleAnchor(property.borders) // top/left/bottom/right - // top - let top = borders[0] - let lineWidth = scaleValue(top.lineWidth) - let stroke = toColor({ color: top.color }, 'white') - parent.append('line') - .attr('x1', x).attr('y1', y) - .attr('x2', endX).attr('y2', y) - .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) - // right - let right = borders[3] - lineWidth = scaleValue(right.lineWidth) - stroke = toColor({ color: right.color }, 'white') - parent.append('line') - .attr('x1',endX).attr('y1', y) - .attr('x2', endX).attr('y2', endY) - .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) - // bottom - let bottom = borders[2] - lineWidth = scaleValue(bottom.lineWidth) - stroke = toColor({ color: bottom.color }, 'white') - parent.append('line') - .attr('x1',endX).attr('y1', endY) - .attr('x2', x).attr('y2', endY) - .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) - // left - let left = borders[1] - lineWidth = scaleValue(left.lineWidth) - stroke = toColor({ color: left.color }, 'white') - parent.append('line') - .attr('x1',x).attr('y1', endY) - .attr('x2', x).attr('y2', y) - .attr('style', `stroke: ${stroke};stroke-width: ${lineWidth}`) - if (property.fillStyle) { - let fill = toPaint(property.fillStyle, anchor) - parent.append('rect') - .attr('x', anchor[0]).attr('y', anchor[1]) - .attr('width', anchor[2]) - .attr('height', anchor[3]) - .attr('fill', fill) - .attr('stroke', 'none') - } - } - - function drawDiagram(obj, parent) { - let property = obj.extInfo.property - let anchor = scaleAnchor(property.anchor) - let g = parent.append('g').attr('id', obj.id).attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - g.attr('transform', `translate(${anchor[0]}, ${anchor[1]})`) - for (let i = 0; i < obj.children.length; i++) { - drawElement(obj.children[i], g) - } - } - - function drawContainer(obj, parent) { - let property = obj.extInfo.property - let _groupFlipX = ctx.groupFlipX - let _groupFlipY = ctx.groupFlipY - let _groupRotation = ctx.groupRotation - let g = shapeHandle(property, parent) - g.attr('id', obj.id).attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - if (property.realType == 'Group') { - let parentGroupFillStyle = ctx.groupFillStyle - let groupFillStyle = property.groupFillStyle - if (groupFillStyle) { - groupFillStyle = JSON.parse(JSON.stringify(groupFillStyle)) - groupFillStyle.groupAnchor = scaleAnchor(property.anchor) - if (parentGroupFillStyle) { - groupFillStyle.parentGroupFillStyle = parentGroupFillStyle - } - } - ctx.groupFillStyle = groupFillStyle - let copyChildren = JSON.parse(JSON.stringify(obj.children)) - recursionGroupChildren(copyChildren, c => { - if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { - let anchor = c.extInfo.property.anchor - anchor[0] *= ctx.interior.scaleX - anchor[1] *= ctx.interior.scaleY - anchor[2] *= ctx.interior.scaleX - anchor[3] *= ctx.interior.scaleY - } - }) - for (let i = 0; i < copyChildren.length; i++) { - drawElement(copyChildren[i], g) - } - ctx.interior = ctx._interior - } else { - for (let i = 0; i < obj.children.length; i++) { - drawElement(obj.children[i], g) - } - } - ctx.groupFlipX = _groupFlipX - ctx.groupFlipY = _groupFlipY - ctx.groupRotation = _groupRotation - } - - function recursionGroupChildren(children, fn) { - if (!children) { - return - } - for (let i = 0; i < children.length; i++) { - let c = children[i] - fn(c) - if (c.extInfo && c.extInfo.property.realType == 'Group') { - continue - } - if (c.children && c.children.length > 0) { - recursionGroupChildren(c.children, fn) - } - } - } - - function drawConnector(obj, parent) { - let property = obj.extInfo.property - let g = parent.append('g').attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - drawGeometry(property, g, obj.id) - } - - function drawGraphicFrame(obj, parent) { - let property = obj.extInfo.property - let anchor = scaleAnchor(property.anchor) - let g = parent.append('g').attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - if (property.chart && property.chart.chartData && property.chart.chartData.length > 0) { - drawChart(property.chart, [0, 0, anchor[2], anchor[3]]).then(canvas => { - let imgSrc = canvas.toDataURL('image/png') - let fill = toPaint({ 'type': 'texture', texture: { 'imageData': imgSrc, stretch: [0, 0, 0, 0] } }, anchor) - g.append('rect') - .attr('id', obj.id) - .attr('width', anchor[2]) - .attr('height', anchor[3]) - .attr('transform', `translate(${anchor[0]}, ${anchor[1]})`) - .attr('fill', fill) - }) - } - } - - function drawTable(obj, parent) { - let property = obj.extInfo.property - let g = parent.append('g').attr('id', obj.id).attr('id', 'g-' + obj.id) - addElementEvent(g, obj) - for (let i = 0; i < obj.children.length; i++) { - let row = obj.children[i] - drawTableRow(obj, row, g) - } - } - - function drawTableRow(table, row, parent) { - let property = row.extInfo.property - for (let i = 0; i < row.children.length; i++) { - let column = row.children[i] - drawText(column, parent) - } - } - - function drawGeometry(property, parent, id) { - if (!parent) { - parent = svg - } - let anchor = scaleAnchor(property.anchor) - let stroke = null - let lineWidth = scaleValue(1) - if (property.strokeStyle) { - lineWidth = scaleValue(property.strokeStyle.lineWidth || 1) - stroke = toPaint(property.strokeStyle.paint, anchor) - } - let paths = geometryPaths(property, zoom) - for (let i = 0; i < paths.length; i++) { - let path = paths[i] - let pathNode = parent.append('path') - if (id) { - pathNode.attr('id', id) - } - pathNode.attr('d', path.path) - let transform = `translate(${anchor[0]},${anchor[1]})` - if (path.scaleX && path.scaleY) { - transform += ` scale(${path.scaleX || 1},${path.scaleY || 1})` - } - pathNode.attr('transform', transform) - let fill = null - if (property.fillStyle) { - let scaleX = 1 / path.scaleX - let scaleY = 1 / path.scaleY - let params = { scaleX, scaleY } - if (property.fillStyle.type == 'bgFill') { - if (ctx.interior) { - params.tx = -ctx.interior.tx - anchor[0] - params.ty = -ctx.interior.ty - anchor[1] - } else { - params.tx = -anchor[0] - params.ty = -anchor[1] - } - params.width = anchor[2] - params.height = anchor[3] - params.rotation = -((property.rotation || 0) + (ctx.groupRotation || 0)) - } - fill = toPaint(property.fillStyle, anchor, params) - } - if (path.filled && fill) { - pathNode.attr('fill', fill) - } else { - pathNode.attr('fill', 'transparent') - } - if (path.stroked) { - pathNode.attr('stroke', stroke) - pathNode.attr('stroke-width', path.scaleY ? lineWidth / path.scaleY : lineWidth) - } - let filter = toShadow(property.shadow, anchor, path.scaleX, path.scaleY) - if (filter) { - pathNode.attr('filter', filter) - } - } - } - - function toShadow(shadow, anchor, scaleX, scaleY) { - if (!shadow) { - return null - } - scaleX = scaleX || 1 - scaleY = scaleY || 1 - let stdDeviation = (shadow.blur || 0) / Math.max(scaleX, scaleY) / 5 - let distance = scaleValue(shadow.distance) - let color = toColor(shadow.fillStyle.color) - let filterId = 'shadow' + (++counter) - let filter = defs.append('filter').attr('id', filterId) - if (anchor && distance && (distance >= anchor[2] / 2 || distance >= anchor[3] / 2)) { - filter.attr('x', '-100%').attr('y', '-100%').attr('width', '400%').attr('height', '400%') - } else { - filter.attr('x', '-50%').attr('y', '-50%').attr('width', '200%').attr('height', '200%') - } - filter.append('feGaussianBlur').attr('in', 'SourceAlpha').attr('stdDeviation', stdDeviation).attr('result', 'blur') - filter.append('feFlood').attr('flood-color', color).attr('result', 'color') - filter.append('feComposite').attr('in', 'color').attr('in2', 'blur').attr('operator', 'in').attr('result', 'shadow') - if (distance) { - let radians = (shadow.angle || 0) * Math.PI / 180 - let x = 0, y = 0 - let rx = distance / scaleX - let ry = distance / scaleY - let shadowOffsetX = x + rx * Math.cos(radians) - let shadowOffsetY = y + ry * Math.sin(radians) - filter.append('feOffset').attr('dx', shadowOffsetX).attr('dy', shadowOffsetY).attr('result', 'offsetBlur') - } - let feMerge = filter.append('feMerge') - feMerge.append('feMergeNode').attr('in', 'offsetBlur') - feMerge.append('feMergeNode').attr('in', 'SourceGraphic') - return `url(#${filterId})` - } - - function toPaint(paint, anchor, params) { - if (!paint) { - return 'transparent' - } else if (paint.type == 'noFill') { - // 无填充 - return 'transparent' - } else if (paint.type == 'color') { - // 颜色 - return toColor(paint.color) - } else if (paint.type == 'bgFill') { - // 背景填充 - if (ctx.bgFillStyle) { - return toPaint(ctx.bgFillStyle, ctx.bgAnchor || anchor, params) - } else { - return 'transparent' - } - } else if (paint.type == 'groupFill') { - // 组合背景 - let groupFillStyle = paint.parentGroupFillStyle || ctx.groupFillStyle - if (groupFillStyle) { - return toPaint(groupFillStyle, scaleAnchor(groupFillStyle.groupAnchor) || anchor, params) - } else { - return 'transparent' - } - } else if (paint.type == 'gradient') { - // 渐变 - let gradient = paint.gradient - let x = 0, y = 0 - let width = anchor[2], height = anchor[3] - let centerX = x + width / 2 - let centerY = y + height / 2 - let gradientNode - // linear,circular,rectangular,shape - if (gradient.gradientType == 'circular') { - // 射线 - let cx = centerX + width * (gradient.insets[1] - gradient.insets[3]) / 2 - let cy = centerY + height * (gradient.insets[0] - gradient.insets[2]) / 2 - // let radius = Math.sqrt(width * width + height * height) * (gradient.insets[1] == 0.5 ? 0.5 : 1) - let _cx = ((cx / width) * 100).toFixed(0) + '%' - let _cy = ((cy / height) * 100).toFixed(0) + '%' - let _r = (gradient.insets[1] * 100).toFixed(0) + '%' - gradientNode = defs.append('radialGradient').attr('cx', _cx).attr('cy', _cy).attr('r', _r).attr('fx', _cx).attr('fy', _cy) - } else { - // 线性 - let startX = x - let startY = centerY - let endX = x + width - let endY = centerY - if (gradient.angle) { - let radians = gradient.angle * Math.PI / 180 - let midX = (startX + endX) / 2 - let midY = (startY + endY) / 2 - let newStartX = midX + (startX - midX) * Math.cos(radians) - (startY - midY) * Math.sin(radians) - let newStartY = midY + (startX - midX) * Math.sin(radians) + (startY - midY) * Math.cos(radians) - let newEndX = midX + (endX - midX) * Math.cos(radians) - (endY - midY) * Math.sin(radians) - let newEndY = midY + (endX - midX) * Math.sin(radians) + (endY - midY) * Math.cos(radians) - startX = newStartX - startY = newStartY - endX = newEndX - endY = newEndY - } - let x1 = ((startX / width) * 100).toFixed(0) + '%' - let y1 = ((startY / height) * 100).toFixed(0) + '%' - let x2 = ((endX / width) * 100).toFixed(0) + '%' - let y2 = ((endY / height) * 100).toFixed(0) + '%' - gradientNode = defs.append('linearGradient').attr('x1', x1).attr('y1', y1).attr('x2', x2).attr('y2', y2) - } - let gradientId = 'gradient' + (++counter) - gradientNode.attr('id', gradientId) - for (let i = 0; i < gradient.colors.length; i++) { - let color = toColor(gradient.colors[i]) - let offset = (gradient.fractions[i] * 100).toFixed(0) + '%' - gradientNode.append('stop').attr('offset', offset).attr('stop-color', color) - } - return `url(#${gradientId})` - } else if (anchor && anchor[2] == 0 && anchor[3] == 0) { - return 'transparent' - } else if (paint.type == 'texture') { - // 图片或纹理 - let texture = paint.texture - let patternId = 'pattern' + (++counter) - let patternNode = defs.append('pattern').attr('id', patternId).attr('patternUnits', 'userSpaceOnUse') - if (params) { - let transform = [] - if (params.scaleX && params.scaleY) { - transform.push(`scale(${params.scaleX}, ${params.scaleY})`) - } - if (params.rotation) { - let width = params.width || anchor[2] - let height = params.height || anchor[3] - transform.push(`rotate(${params.rotation}, ${width / 2}, ${height / 2})`) - } - if (params.tx != null && params.ty != null) { - transform.push(`translate(${params.tx}, ${params.ty})`) - } - if (transform.length > 0) { - patternNode.attr('patternTransform', transform.join(' ')) - } - } - loadImage(texture.imageData).then(img => { - if (img) { - texturePattern(patternNode, img, texture, anchor) - } - }) - return `url(#${patternId})` - } else if (paint.type == 'pattern') { - // 图案 - let pattern = paint.pattern - // let prst = pattern.prst - let fgColor = pattern.fgColor.realColor - let bgColor = pattern.bgColor.realColor - let width = anchor[2], height = anchor[3] - let imgCanvas = document.createElement('canvas') - imgCanvas.width = width - imgCanvas.height = height - let imgCtx = imgCanvas.getContext('2d') - imgCtx.imageSmoothingEnabled = true - imgCtx.imageSmoothingQuality = 'high' - let imgData = imgCtx.createImageData(width, height) - let line = 0 - for (let i = 0; i < imgData.data.length; i += 4) { - if (++line % 16 == 0) { - // 前景 - imgData.data[i + 0] = (fgColor >> 16) & 255 - imgData.data[i + 1] = (fgColor >> 8) & 255 - imgData.data[i + 2] = (fgColor >> 0) & 255 - imgData.data[i + 3] = (fgColor >> 24) & 255 - } else { - // 背景 - imgData.data[i + 0] = (bgColor >> 16) & 255 - imgData.data[i + 1] = (bgColor >> 8) & 255 - imgData.data[i + 2] = (bgColor >> 0) & 255 - imgData.data[i + 3] = (bgColor >> 24) & 255 - } - if (i % 400 == 0) { - line += 2 - } - } - imgCtx.putImageData(imgData, 0, 0) - let imgSrc = imgCanvas.toDataURL('image/png') - let patternId = 'pattern' + (++counter) - let patternNode = defs.append('pattern') - patternNode.attr('id', patternId) - .attr('width', width) - .attr('height', height) - .attr('patternUnits', 'userSpaceOnUse') - patternNode.append('image') - .attr('href', imgSrc) - .attr('x', 0) - .attr('y', 0) - .attr('width', width) - .attr('height', height) - if (params) { - let transform = [] - if (params.scaleX && params.scaleY) { - transform.push(`scale(${params.scaleX},${params.scaleY})`) - } - if (transform.length > 0) { - patternNode.attr('patternTransform', transform.join(' ')) - } - } - return `url(#${patternId})` - } - } - - function texturePattern(patternNode, img, texture, anchor) { - let width = anchor[2] - let height = anchor[3] - if (width < 1 && height < 1 || isNaN(width) || isNaN(height)) { - width = img.width - height = img.height - } - if (texture.alignment || !texture.stretch) { - // 图片平铺 - width = img.width - height = img.height - } - patternNode.attr('width', width).attr('height', height) - let patternCanvas = document.createElement('canvas') - patternCanvas.width = Math.max(1, width) - patternCanvas.height = Math.max(1, height) - let patternCtx = patternCanvas.getContext('2d') - patternCtx.imageSmoothingEnabled = true - patternCtx.imageSmoothingQuality = 'high' - if (texture.alpha >= 0 && texture.alpha < 100000) { - patternCtx.globalAlpha = texture.alpha / 100000 - } - let imgInsets = null - if (texture.insets) { - let top = texture.insets[0] / 100000 - let left = texture.insets[1] / 100000 - let bottom = texture.insets[2] / 100000 - let right = texture.insets[3] / 100000 - let x = img.width * left - let y = img.height * top - let w = img.width * (1 - left - right) - let h = img.height * (1 - top - bottom) - imgInsets = [x, y, w, h] - } - if (texture.stretch) { - let top = texture.stretch[0] / 100000 - let left = texture.stretch[1] / 100000 - let bottom = texture.stretch[2] / 100000 - let right = texture.stretch[3] / 100000 - let x = width * left - let y = height * top - let w = width * (1 - left - right) - let h = height * (1 - top - bottom) - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], x, y, w, h) - } else { - patternCtx.drawImage(img, x, y, w, h) - } - } else if (texture.alignment) { - let x = 0, y = 0, scale = zoom - if (texture.alignment == 'CENTER') { - if (width > anchor[2] / scale) { - x = (width - anchor[2] / scale) / 2 - } - if (height > anchor[3] / scale) { - y = (height - anchor[3] / scale) / 2 - } - } - if (!x && !y) { - scale = Math.max(scale, 1) - } - patternCtx.drawImage(img, x, y, width, height, 0, 0, width * scale, height * scale) - } else { - if (imgInsets) { - patternCtx.drawImage(img, imgInsets[0], imgInsets[1], imgInsets[2], imgInsets[3], 0, 0, width, height) - } else { - patternCtx.drawImage(img, 0, 0, width, height) - } - } - if (texture.duoTone && texture.duoTone.length > 0 && texture.duoTonePrst) { - try { - // 重新着色 - let color = texture.duoTone[0].realColor - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let imageData = patternCtx.getImageData(0, 0, patternCanvas.width, patternCanvas.height) - let data = imageData.data - for(var i = 0; i < data.length; i += 4) { - let gray = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11) / 255 - // black / white - let prst = texture.duoTonePrst == 'white' ? 255 : 0 - data[i] = gray * r + (1 - gray) * prst - data[i + 1] = gray * g + (1 - gray) * prst - data[i + 2] = gray * b + (1 - gray) * prst - } - patternCtx.putImageData(imageData, 0, 0) - } catch(e) { /* empty */ } - } - // let mode = texture.alignment ? 'repeat' : 'no-repeat' - let imgSrc = patternCanvas.toDataURL('image/png') - patternNode.append('image') - .attr('href', imgSrc) - .attr('x', 0) - .attr('y', 0) - .attr('width', width) - .attr('height', height) - } - - function toColor(colorObj, defaultColor) { - if (colorObj == null || (colorObj.color == null && colorObj.realColor == null)) { - return defaultColor || 'transparent' - } - let color = colorObj.realColor != null ? colorObj.realColor : colorObj.color - let r = (color >> 16) & 255 - let g = (color >> 8) & 255 - let b = (color >> 0) & 255 - let a = ((color >> 24) & 255) / 255 - if (colorObj.realColor == null) { - if (colorObj.alpha != null && colorObj.alpha != -1) { - if (colorObj.alpha > 1000) { - a = colorObj.alpha / 100000 - } else { - a = (colorObj.alpha > 0 && colorObj.alpha < 1) ? colorObj.alpha : colorObj.alpha / 255 - } - a = Math.min(1, Math.max(0, a)) - } - if (colorObj.lumMod && colorObj.lumMod > 0) { - let value = colorObj.lumMod / 100000 - r = r * value - g = g * value - b = b * value - } - if (colorObj.lumOff && colorObj.lumOff > 0) { - let value = colorObj.lumOff / 100000 - r += 255 * value - g += 255 * value - b += 255 * value - } - } - return `rgba(${r}, ${g}, ${b}, ${a})` - } - - function toColorValue(r, g, b, a) { - a = (a == null ? 255 : a) - return (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0 - } - - function text(obj) { - if (obj == null) { - return null - } - let text = obj.text - if (text != null) { - return text - } - if (obj.children != null && obj.children.length > 0) { - let textAll = '' - for (let i = 0; i < obj.children.length; i++) { - let p = obj.children[i] - if (p.children == null) { - continue - } - let pText = '' - for (let j = 0; j < p.children.length; j++) { - let r = p.children[j] - if (r.text == null) { - continue - } - pText += r.text - } - if (pText) { - textAll += (pText + '\n') - } - } - if (textAll.length > 0) { - textAll = textAll.substring(0, textAll.length - 1) - } - return textAll - } - return '' - } - - function loadImage(src) { - return new Promise(resolve => { - if (!src) { - resolve() - return - } - let cacheKey - if (src.length < 15) { - cacheKey = src - } else { - cacheKey = src.length + '_' + src.substring(src.length - 15) - } - let img = imageCache[cacheKey] - if (img == null) { - img = new Image() - let eqOrigin = src.startsWith('data:') || src.startsWith(document.location.origin) || (src.startsWith('//') && (document.location.protocol + src).startsWith(document.location.origin)) - if (!eqOrigin) { - img.crossOrigin = 'anonymous' - } - img.src = src - img.onload = function() { - imageCache[cacheKey] = img - resolve(img) - } - img.onerror = function (e) { - resolve() - console.log('图片加载失败: ', src, e) - } - } else { - resolve(img) - } - }) - } - - function calcPointList(page) { - pointList = [] - recursion(page.children, c => { - if (c.extInfo && c.extInfo.property && c.extInfo.property.anchor) { - let point = scaleAnchor(c.point) - if (!point) { - point = scaleAnchor(c.extInfo.property.anchor) - } - let _point - if (point[2] < 0.1) { - let width = scaleValue((c.extInfo.property.strokeStyle || {}).lineWidth || 1) - let x = point[0] - width / 2 - _point = { x: x, endX: x + width, y: point[1], endY: point[1] + point[3], sort: width + point[3], obj: c } - } else if (point[3] < 0.1) { - let height = scaleValue((c.extInfo.property.strokeStyle || {}).lineWidth || 1) - let y = point[1] - height / 2 - _point = { x: point[0], endX: point[0] + point[2], y: y, endY: y + height, sort: point[2] + height, obj: c } - } else { - _point = { x: point[0], endX: point[0] + point[2], y: point[1], endY: point[1] + point[3], sort: point[2] + point[3], obj: c } - } - pointList.push(_point) - } - }) - pointList.sort((p1, p2) => p1.sort > p2.sort ? 1 : -1) - } - - function removePoint() { - if (currentPoint && currentPoint.obj && (!currentSelect || currentPoint.obj.id != currentSelect.id)) { - let gNode = document.getElementById('g-' + currentPoint.obj.id) - if (gNode) { - gNode.style.cursor = null - gNode.style.outline = null - } - } - currentPoint = null - } - - function showPoint(point) { - removePoint() - currentPoint = point - let gNode = document.getElementById('g-' + currentPoint.obj.id) - if (gNode && (!currentSelect || currentPoint.obj.id != currentSelect.id)) { - gNode.style.cursor = 'move' - gNode.style.outline = '1px dashed #777' - } - } - - function addElementEvent(gNode, elementObj) { - let node = gNode.node() - node.addEventListener('click', function (e) { - if (currentPoint && currentSelect && currentPoint.obj.id == currentSelect.id) { - if (!document.getElementById('move_element_operate')) { - addElementMoveScale(elementObj) - } - return - } - if (currentPoint && currentPoint.obj.id != elementObj.id && (currentPoint.obj.type == 'text' || currentPoint.obj.type == 'freeform')) { - // 文本被遮挡处理 - let rId = null - for (let i = 0; i < currentPoint.obj.children.length; i++) { - let p = currentPoint.obj.children[i] - for (let j = 0; j < p.children.length; j++) { - let r = p.children[j] - let rNode = document.getElementById(r.id) - let rect = rNode.getBoundingClientRect() - if (e.clientX >= rect.x && e.clientX <= rect.x + rect.width && e.clientY >= rect.y && e.clientY <= rect.y + rect.height) { - rId = r.id - if (r.text && r.text.trim()) { - break - } - } - } - if (rId) { - break - } - } - if (rId) { - editRunText(rId, currentPoint.obj) - e.cancelBubble = true - return - } - } - if (currentPoint && currentPoint.obj.id != elementObj.id) { - addElementMoveScale(elementObj) - } else if (!currentPoint) { - removeElementMoveScale() - } - }) - node.addEventListener('mousedown', function (e) { - if (!currentPoint) { - return - } - if (!currentSelect || currentPoint.obj.id != currentSelect.id) { - addElementMoveScale(currentPoint.obj) - } - doElementMove(e, currentPoint.obj) - }) - } - - function addRunTextEvent(rNode, textObj) { - let rId = rNode.attr('id') - let node = rNode.node() - // node.addEventListener('mouseenter', function () { - // node.style.outline = '1px dashed #f35858' - // }) - // node.addEventListener('mouseleave', function () { - // node.style.outline = null - // }) - node.addEventListener('click', function (e) { - editRunText(rId, textObj) - e.cancelBubble = true - }) - } - - function doElementMove(e, obj) { - // 移动 - if (obj.type == 'tableColumn') { - // table - obj = idMap[idMap[obj.pid].pid] - } - if (!obj.point) { - return - } - let gNode = document.getElementById('g-' + obj.id) - if (!gNode) { - return - } - let x = e.clientX - let y = e.clientY - let g = d3.select(gNode) - let flipX = parseInt(g.attr('groupFlipX') || 1) - let flipY = parseInt(g.attr('groupFlipY') || 1) - let lastTranslate = g.translate() - let translateX = lastTranslate.x - let translateY = lastTranslate.y - let updateAnchor = (obj, tx, ty) => { - let point = obj.point - point[0] = point[0] + tx * flipX - point[1] = point[1] + ty * flipY - let anchor = obj.extInfo.property.anchor - if (point !== anchor) { - anchor[0] = anchor[0] + tx * (anchor[2] / point[2]) - anchor[1] = anchor[1] + ty * (anchor[3] / point[3]) - } - let interiorAnchor = obj.extInfo.property.interiorAnchor - if (interiorAnchor) { - interiorAnchor[0] = interiorAnchor[0] + tx * (interiorAnchor[2] / point[2]) - interiorAnchor[1] = interiorAnchor[1] + ty * (interiorAnchor[3] / point[3]) - } - if (obj.type == 'table') { - let rows = obj.children || [] - for (let i = 0; i < rows.length; i++) { - let columns = rows[i].children || [] - for (let j = 0; j < columns.length; j++) { - let columnAnchor = columns[j].extInfo.property.anchor - columnAnchor[0] = columnAnchor[0] + tx - columnAnchor[1] = columnAnchor[1] + ty - } - } - } - } - let rotate = g.rotate() - let move_element_operate = document.getElementById('move_element_operate') - let tx = 0, ty = 0 - let lastMoveX = +(g.attr('moveX') || 0) - let lastMoveY = +(g.attr('moveY') || 0) - document.onmousemove = function (e2) { - tx = (e2.clientX - x) * flipX - ty = (e2.clientY - y) * flipY - if (move_element_operate) { - move_element_operate.remove() - move_element_operate = null - currentSelect = null - } - if (rotate) { - g.rotate(0) - } - g.translate(translateX + tx, translateY + ty) - } - let cursor = g.style('cursor') - g.style('cursor', 'move') - document.onmouseup = function (e2) { - g.style('cursor', cursor) - document.onmousemove = null - document.onmouseup = null - if (rotate) { - g.rotate(rotate.rotate, rotate.x, rotate.y) - } - if (tx || ty) { - const real_tx = tx / zoom - const real_ty = ty / zoom - updateAnchor(obj, real_tx, real_ty) - if (obj != idMap[obj.id]) { - updateAnchor(idMap[obj.id], real_tx, real_ty) - } - g.attr('moveX', lastMoveX + tx) - g.attr('moveY', lastMoveY + ty) - // 重新渲染元素 - // $this.redrawElementWithId(obj.id) - // 不重新渲染,重新计算元素位置 - page && calcPointList(page) - if ($this.onchange) { - $this.onchange(page, 'move', obj, e2) - } - } - setTimeout(() => addElementMoveScale(obj), 10) - } - } - - function doElementRotate(e, obj) { - // 旋转 - if (obj.type == 'tableColumn') { - // table - obj = idMap[idMap[obj.pid].pid] - } - if (!obj.point) { - return - } - let gNode = document.getElementById('g-' + obj.id) - if (!gNode) { - return - } - let g = d3.select(gNode) - let flipX = parseInt(g.attr('groupFlipX') || 1) - let flipY = parseInt(g.attr('groupFlipY') || 1) - let rotate = g.rotate() - if (!rotate.rotate && !rotate.x) { - let anchor = scaleAnchor(obj.extInfo?.property?.anchor ? obj.extInfo.property.anchor : obj.point) - let interior = g.attr('interior') - if (interior) { - interior = JSON.parse(interior) - anchor = [anchor[0] * interior.scaleX + interior.tx * zoom, anchor[1] * interior.scaleY + interior.ty * zoom, anchor[2] * interior.scaleX, anchor[3] * interior.scaleY] - } - let cx = anchor[0] + anchor[2] / 2 - let cy = anchor[1] + anchor[3] / 2 - rotate = { rotate: 0, x: cx, y: cy, interior: true } - } - let rect = gNode.getBoundingClientRect() - let centerX = rect.x + rect.width / 2 - let centerY = rect.y + rect.height / 2 - let startAngle = Math.atan2(e.clientY - centerY, e.clientX - centerX) * 180 / Math.PI - rotate.rotate - let updateRotate = (obj, angle) => { - obj.extInfo.property.rotation = angle - } - let angle = 0 - let move_rotate_span = document.createElement('span') - move_rotate_span.id = 'move_rotate_span' - move_rotate_span.style.fontSize = '14px' - move_rotate_span.style.color = '#5f6063' - move_rotate_span.style.position = 'fixed' - move_rotate_span.style.left = e.clientX + 'px' - move_rotate_span.style.top = e.clientY + 'px' - move_rotate_span.style.margin = '-20px 0px 0px 12px' - move_rotate_span.innerText = rotate.rotate.toFixed(0) + '°' - document.body.appendChild(move_rotate_span) - let move_element_operate = document.getElementById('move_element_operate') - document.onmousemove = function (e2) { - if (move_element_operate) { - move_element_operate.remove() - move_element_operate = null - currentSelect = null - } - let endAngle = Math.atan2(e2.clientY - centerY, e2.clientX - centerX) * 180 / Math.PI - angle = (endAngle - startAngle) % 360 * flipX - angle = +(angle < 0 ? angle + 360 : angle).toFixed(0) - g.rotate(angle, rotate.x, rotate.y) - move_rotate_span.style.left = e2.clientX + 'px' - move_rotate_span.style.top = e2.clientY + 'px' - move_rotate_span.innerText = angle + '°' - } - document.onmouseup = function (e2) { - document.onmousemove = null - document.onmouseup = null - move_rotate_span.remove() - if (angle) { - updateRotate(obj, angle) - if (obj != idMap[obj.id]) { - updateRotate(idMap[obj.id], angle) - } - if (rotate.interior) { - // 重新渲染元素 - $this.redrawElementWithId(obj.id) - } else { - // 不重新渲染,重新计算元素位置 - page && calcPointList(page) - setTimeout(() => addElementMoveScale(obj), 10) - } - if ($this.onchange) { - $this.onchange(page, 'rotate', obj, e2) - } - } else { - setTimeout(() => addElementMoveScale(obj), 10) - } - } - } - - function rotatePoint(pointX, pointY, centerX, centerY, angle) { - angle = angle * Math.PI / 180 - let rotatedX = Math.cos(angle) * (pointX - centerX) - Math.sin(angle) * (pointY - centerY) + centerX - let rotatedY = Math.sin(angle) * (pointX - centerX) + Math.cos(angle) * (pointY - centerY) + centerY - return [rotatedX, rotatedY] - } - - function addElementMoveScale(elementObj) { - removeElementMoveScale() - if (!elementObj) { - return - } - if (!elementObj.point || elementObj.type == 'tableColumn') { - return - } - let gNode = document.getElementById('g-' + elementObj.id) - if (!gNode) { - return - } - console.log('obj', elementObj) - let g = d3.select(gNode) - currentSelect = elementObj - // gNode.style.outline = '1px dashed #f35858' - let isText = (elementObj.type == 'text' || elementObj.type == 'freeform') && elementObj.children && elementObj.children.length > 0 - if (isText) { - let hasRs = false - for (let i = 0; i < elementObj.children.length; i++) { - if (elementObj.children[i].children && elementObj.children[i].children.length > 0) { - hasRs = true - break - } - } - isText = hasRs - } - let svgNode = svg.node() - let svgRect = svgNode.getClientRects()[0] - let x = svgRect.x + elementObj.point[0] * zoom - let y = svgRect.y + elementObj.point[1] * zoom - let width = elementObj.point[2] * zoom - let height = elementObj.point[3] * zoom - let moveElements = [ - { left: '0px', top: '0px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nwse-resize' }, - { left: width / 2 + 'px', top: '0px', width: '16px', height: '8px', margin: '-4px 0px 0px -8px', cursor: 'ns-resize' }, - { left: width + 'px', top: '0px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nesw-resize' }, - { left: width + 'px', top: height / 2 + 'px', width: '8px', height: '16px', margin: '-8px 0px 0px -4px', cursor: 'ew-resize' }, - { left: width + 'px', top: height + 'px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nwse-resize' }, - { left: width / 2 + 'px', top: height + 'px', width: '16px', height: '8px', margin: '-4px 0px 0px -8px', cursor: 'ns-resize' }, - { left: '0px', top: height + 'px', width: '10px', height: '10px', margin: '-5px 0px 0px -5px', cursor: 'nesw-resize' }, - { left: '0px', top: height / 2 + 'px', width: '8px', height: '16px', margin: '-8px 0px 0px -4px', cursor: 'ew-resize' } - ] - let div = document.createElement('div') - div.id = 'move_element_operate' - div.style.zIndex = 9999 - div.style.position = 'fixed' - div.style.userSelect = 'none' - div.style.pointerEvents = 'none' - div.style.left = x + 'px' - div.style.top = y + 'px' - div.style.width = width + 'px' - div.style.height = height + 'px' - div.style.outline = '1px dashed #f35858' - let rotate = g.rotate().rotate - if (rotate) { - div.style.transform = `rotate(${rotate}deg)` - } - for (let i = 0; i < moveElements.length; i++) { - if (isText && (i == 1 || i == 5)) { - continue - } - let obj = moveElements[i] - let span = document.createElement('span') - span.id = 'move_span_' + i - span.style.pointerEvents = 'all' - span.style.position = 'absolute' - span.style.background = '#fff' - span.style.borderRadius = '5px' - span.style.border = '1px solid #a1a4ad' - span.style.left = obj.left - span.style.top = obj.top - span.style.width = obj.width - span.style.height = obj.height - span.style.cursor = obj.cursor - span.style.margin = obj.margin - span.addEventListener('mousedown', function (e) { - // 缩放 - doElementMoveScale(e, elementObj, i) - }) - div.appendChild(span) - } - let img = document.createElement('img') - img.id = 'move_rotate_img' - img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkNFRjkzREQyQUVBRDExRUE5RDkwQTZCNzUwQUEwQkI5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkNFRjkzREQzQUVBRDExRUE5RDkwQTZCNzUwQUEwQkI5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6Q0VGOTNERDBBRUFEMTFFQTlEOTBBNkI3NTBBQTBCQjkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6Q0VGOTNERDFBRUFEMTFFQTlEOTBBNkI3NTBBQTBCQjkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6qKiSpAAACtElEQVR42pRUX2iSURQ/3/4Qpc6EHipKrdwcGOxlDCsI11gPbWt/zCnR2GqNELZRsJ4qG8Sgh+qlxmJREQS1VUTSgiLIoMXoUQVJ9segsIf56cypn06/zrG78WlEeuD3ne/cc+/vnnPuuZcTRREkYkbYEROIF1CEtLQe3/gvk4xfiERWnp/s6WtihHIoUSrWiZYC326d7h+AxaUAhMPhpsrKyl9yuTyFvjBiHjGHmEZ8+RcZx9L0m5qOViMhfA/Mg1KphHQ6DalUClQqFeh0OjAajdDd3Q0NDQ1TrAwf/0oTDQ4XTt6fvAsatRp2aXXA8zxEo9FVFPB4PDA2NgYKhQKsVivYbDYrznfhWnVhZFQzrqPTPFGlrLr26uUzOHTwACSSyc+tbe01w8Pnd3yandVrtdq2kZGL130+H8RiMXA4HMDqmp/msZa2ctQyxLbRUYe5Vq+3LCwsPrl0+YoTx6hmIkN2/M7tIzLZlscGgwHcbjeVYGeX2RKUklF0mxEqRBU7lDhiFZGmOSwDGuemp57eGBoatNbX14Pdbh/EDMalaYpsUYydHI9YYWTxAqzxfGjOZDKBy+UCPLxGttkfspnXznUymhxhZFEiQ18hWSIY/Ompq6sDr9cLHMftzyOjj4RQQCTZf3bdh8iw+glf/f5FjUYDwWCuVNvzGp/6rFgIgmBJp9c+ZLNZEaMSSTKZzDtU7Vj7vOv0X8Fbca73zFmTVlcLu/dUg2afHvr6B5o32qTYqHBnjiJbDoXEw43NonpvTU6TjU3cSf5SIuM6u044yzju6qOH93K3hTTZ7R1db8hfVuLDUH6qp/cBRnrz/duZH6TJpnHpRS/m3aKNNyG2sganRk+w3qSWEipKiIp2zTCCctZCKWavkb/oNAuam6JZZjpeMlkBYYJdtwSzc7X6LcAAZxVxcQ2YXyMAAAAASUVORK5CYII=' - img.style.pointerEvents = 'all' - img.style.position = 'absolute' - img.style.left = width + 'px' - img.style.top = '0px' - img.style.width = '20px' - img.style.height = '20px' - img.style.margin = '-15px 0px 0px 0px' - img.style.cursor = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABWUlEQVQ4T6WT0U3DQAyGf/sGoBuQDcjp7p2wQTsBbNCOABMAE5BuwAjpe09XJqAjlAFyRq5yIUkRKuCXSIn92f79h/DPoGl9jLFIKS0BzAEU+l1EdgBqY8zaWnvQnLZtS+/96wgQQrgD8PLDUHsADwAeAbw556oeMCwWkQ8iqpn5NaVUikhJRLcT8KYHdGO/dwkbZp7rqMOCEMKq65xffwFCCE8AltrZGFNMi7sGEcBsAB0BdLdLAM/OOe00ihhjlVK6n7yunXP1UYMQguiTmW+stc1vLjsCiMhCT/MXgN75SkTW3ns95dmRJ+gVZmZrrVXgSWy327kxphmKfATEGGcpJS1SIQ/MvJhqkc+orvTe20zvjRRjLNu2bYjoItuXiBoRKYiozLZWBzJzlacYWVkhKSX1xPV3K6hGxpjVyQrTZN2161qJyJ6Idmpra636ZRQnf+PZ8neJn9q+rxFGGvPWAAAAAElFTkSuQmCC) 8 8,default' - img.addEventListener('mousedown', function (e) { - // 旋转 - doElementRotate(e, elementObj) - }) - div.appendChild(img) - document.body.appendChild(div) - if ($this.onselect) { - $this.onselect(page, elementObj) - } - } - - function removeElementMoveScale() { - let gNode = currentSelect ? document.getElementById('g-' + currentSelect.id) : null - if (gNode) { - gNode.style.outline = null - } - currentSelect = null - let element = document.getElementById('move_element_operate') - element && element.remove() - if ($this.onunselect) { - $this.onunselect(page) - } - } - - function doElementMoveScale(e, obj, idx) { - // 移动缩放 - if (obj.type == 'tableColumn') { - // table - obj = idMap[idMap[obj.pid].pid] - } - if (!obj.point) { - return - } - let gNode = document.getElementById('g-' + obj.id) - if (!gNode) { - return - } - let x = obj.point[0] * zoom - let y = obj.point[1] * zoom - let width = obj.point[2] * zoom - let height = obj.point[3] * zoom - let clientX = e.clientX - let clientY = e.clientY - let g = d3.select(gNode) - let lastScale = g.scale() - let scaleX = lastScale.x - let scaleY = lastScale.y - let rect = gNode.getBoundingClientRect() - let centerX = rect.x + rect.width / 2 - let centerY = rect.y + rect.height / 2 - let lastRotate = g.rotate() - if (lastRotate.rotate) { - let clientXY = rotatePoint(clientX, clientY, centerX, centerY, -lastRotate.rotate) - clientX = clientXY[0] - clientY = clientXY[1] - } - let lastTranslate = g.translate() - let translateX = lastTranslate.x - let translateY = lastTranslate.y - let changeData = { tx: 0, ty: 0, scaleX: 1, scaleY: 1 } - let changeElement = (tx, ty) => { - let _scaleX = 1, _scaleY = 1 - let originalWidth = width / scaleX - let originalHeight = height / scaleY - let lastTx, originalX, newTx, newScaleX, originalTranslateX - let lastTy, originalY, newTy, newScaleY, originalTranslateY - switch (idx) { - case 0: - // 左上角 - _scaleX = (width - tx) / width - _scaleY = (height - ty) / height - if (_scaleX < 0.15 || _scaleY < 0.15) { - return false - } - changeData.tx = tx - changeData.ty = ty - changeData.scaleX = _scaleX - changeData.scaleY = _scaleY - // g.translate(translateX + tx + x * (1 - _scaleX), translateY + ty + y * (1 - _scaleY)) - // g.scale(scaleX * _scaleX, scaleY * _scaleY) - lastTx = originalWidth - width - originalX = x - lastTx - newTx = x - originalX + tx - newScaleX = (originalWidth - newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - lastTy = originalHeight - height - originalY = y - lastTy - newTy = y - originalY + ty - newScaleY = (originalHeight - newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), originalTranslateY + newTy + originalY * (1 - newScaleY)) - g.scale(newScaleX, newScaleY) - break - case 1: - // 上 - _scaleY = (height - ty) / height - if (_scaleY < 0.15) { - return false - } - changeData.ty = ty - changeData.scaleY = _scaleY - // g.translate(translateX, translateY + ty + y * (1 - _scaleY)) - // g.scale(scaleX, scaleY * _scaleY) - lastTy = originalHeight - height - originalY = y - lastTy - newTy = y - originalY + ty - newScaleY = (originalHeight - newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(translateX, originalTranslateY + newTy + originalY * (1 - newScaleY)) - g.scale(scaleX, newScaleY) - break - case 2: - // 右上角 - _scaleX = (width + tx) / width - _scaleY = (height - ty) / height - if (_scaleX < 0.15 || _scaleY < 0.15) { - return false - } - changeData.ty = ty - changeData.scaleX = _scaleX - changeData.scaleY = _scaleY - // g.translate(translateX + x * (1 - _scaleX), translateY + ty + y * (1 - _scaleY)) - // g.scale(scaleX * _scaleX, scaleY * _scaleY) - lastTx = width - originalWidth - originalX = x - newTx = lastTx + tx - newScaleX = (originalWidth + newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - lastTy = originalHeight - height - originalY = y - lastTy - newTy = y - originalY + ty - newScaleY = (originalHeight - newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(originalTranslateX + originalX * (1 - newScaleX), originalTranslateY + newTy + originalY * (1 - newScaleY)) - g.scale(newScaleX, newScaleY) - break - case 3: - // 右 - _scaleX = (width + tx) / width - if (_scaleX < 0.15) { - return false - } - changeData.scaleX = _scaleX - // g.translate(translateX + x * (1 - _scaleX), translateY) - // g.scale(scaleX * _scaleX, scaleY) - lastTx = width - originalWidth - originalX = x - newTx = lastTx + tx - newScaleX = (originalWidth + newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - g.translate(originalTranslateX + originalX * (1 - newScaleX), translateY) - g.scale(newScaleX, scaleY) - break - case 4: - // 右下角 - _scaleX = (width + tx) / width - _scaleY = (height + ty) / height - if (_scaleX < 0.15 || _scaleY < 0.15) { - return false - } - changeData.scaleX = _scaleX - changeData.scaleY = _scaleY - // g.translate(translateX + x * (1 - _scaleX), translateY + y * (1 - _scaleY)) - // g.scale(scaleX * _scaleX, scaleY * _scaleY) - lastTx = width - originalWidth - originalX = x - newTx = lastTx + tx - newScaleX = (originalWidth + newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - lastTy = height - originalHeight - originalY = y - newTy = lastTy + ty - newScaleY = (originalHeight + newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(originalTranslateX + originalX * (1 - newScaleX), originalTranslateY + originalY * (1 - newScaleY)) - g.scale(newScaleX, newScaleY) - break - case 5: - // 下 - _scaleY = (height + ty) / height - if (_scaleY < 0.15) { - return false - } - changeData.scaleY = _scaleY - // g.translate(translateX, translateY + y * (1 - _scaleY)) - // g.scale(scaleX, scaleY * _scaleY) - lastTy = height - originalHeight - originalY = y - newTy = lastTy + ty - newScaleY = (originalHeight + newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(translateX, originalTranslateY + originalY * (1 - newScaleY)) - g.scale(scaleX, newScaleY) - break - case 6: - // 左下角 - _scaleX = (width - tx) / width - _scaleY = (height + ty) / height - if (_scaleX < 0.15 || _scaleY < 0.15) { - return false - } - changeData.scaleX = _scaleX - changeData.scaleY = _scaleY - changeData.tx = tx - // g.translate(translateX + tx + x * (1 - _scaleX), translateY + y * (1 - _scaleY)) - // g.scale(scaleX * _scaleX, scaleY * _scaleY) - lastTx = originalWidth - width - originalX = x - lastTx - newTx = x - originalX + tx - newScaleX = (originalWidth - newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - lastTy = height - originalHeight - originalY = y - newTy = lastTy + ty - newScaleY = (originalHeight + newTy) / originalHeight - originalTranslateY = +(g.attr('moveY') || 0) * newScaleY - g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), originalTranslateY + originalY * (1 - newScaleY)) - g.scale(newScaleX, newScaleY) - break - case 7: - // 左 - _scaleX = (width - tx) / width - if (_scaleX < 0.15) { - return false - } - changeData.tx = tx - changeData.scaleX = _scaleX - // g.translate(translateX + tx + x * (1 - _scaleX), translateY) - // g.scale(scaleX * _scaleX, scaleY) - lastTx = originalWidth - width - originalX = x - lastTx - newTx = x - originalX + tx - newScaleX = (originalWidth - newTx) / originalWidth - originalTranslateX = +(g.attr('moveX') || 0) * newScaleX - g.translate(originalTranslateX + newTx + originalX * (1 - newScaleX), translateY) - g.scale(newScaleX, scaleY) - break - } - return true - } - let updateElement = (obj) => { - let _tx = changeData.tx / zoom - let _ty = changeData.ty / zoom - let point = obj.point - point[0] = point[0] + _tx - point[1] = point[1] + _ty - let _width = point[2] - let _height = point[3] - point[2] = point[2] * changeData.scaleX - point[3] = point[3] * changeData.scaleY - let anchor = obj.extInfo.property.anchor - if (point !== anchor) { - anchor[0] = anchor[0] + _tx * (anchor[2] / _width) - anchor[1] = anchor[1] + _ty * (anchor[3] / _height) - anchor[2] = anchor[2] * changeData.scaleX - anchor[3] = anchor[3] * changeData.scaleY - } - let interiorAnchor = obj.extInfo.property.interiorAnchor - if (interiorAnchor) { - interiorAnchor[0] = interiorAnchor[0] + _tx * (interiorAnchor[2] / point[2]) - interiorAnchor[1] = interiorAnchor[1] + _ty * (interiorAnchor[3] / point[3]) - } - if (obj.type == 'table') { - let rows = obj.children || [] - for (let i = 0; i < rows.length; i++) { - let row_property = rows[i].extInfo.property - row_property.rowHeight *= changeData.scaleY - let columns = rows[i].children || [] - for (let j = 0; j < columns.length; j++) { - let columns_property = columns[j].extInfo.property - columns_property.columnWidth *= changeData.scaleX - let columnAnchor = columns[j].extInfo.property.anchor - columnAnchor[0] = anchor[0] + columns_property.columnWidth * j + (j + 1) * changeData.scaleX - columnAnchor[1] = anchor[1] + row_property.rowHeight * i + (i + 1) * changeData.scaleY - columnAnchor[2] = columns_property.columnWidth - columnAnchor[3] = row_property.rowHeight - } - } - } - } - let move_element_operate = document.getElementById('move_element_operate') - let tx = 0, ty = 0 - document.onmousemove = function (e2) { - let clientX2 = e2.clientX - let clientY2 = e2.clientY - if (lastRotate.rotate) { - let clientXY2 = rotatePoint(clientX2, clientY2, centerX, centerY, -lastRotate.rotate) - clientX2 = clientXY2[0] - clientY2 = clientXY2[1] - } - tx = clientX2 - clientX - ty = clientY2 - clientY - if (move_element_operate) { - move_element_operate.remove() - move_element_operate = null - currentSelect = null - } - let change = changeElement(tx, ty) - if (!change) { - e.preventDefault() - } - } - document.onmouseup = function (e2) { - document.onmousemove = null - document.onmouseup = null - if (tx || ty) { - updateElement(obj) - if (obj != idMap[obj.id]) { - updateElement(idMap[obj.id]) - } - // 重新渲染 - // $this.drawPptx(pptx, pageIndex, obj.id) - // 重新渲染元素 - $this.redrawElementWithId(obj.id) - if ($this.onchange) { - $this.onchange(page, 'scale', obj, e2) - } - } else { - addElementMoveScale(obj) - } - } - } - - function editRunText(rId, textObj) { - if (mode != 'edit') { - return - } - let obj = idMap[rId] - if (obj == null) { - // ignore master element - return - } - addElementMoveScale(textObj) - let rect = null - let nodeStyle = null - let nodes = document.querySelectorAll(`tspan[id='${rId}']`) - for (let i = 0; i < nodes.length; i++) { - let _rect = nodes[i].getBoundingClientRect() - if (_rect.width == 0 || _rect.height == 0) { - continue - } - if (rect == null) { - rect = { x: _rect.x, y: _rect.y, endX: _rect.x + _rect.width, endY: _rect.y + _rect.height } - nodeStyle = window.getComputedStyle(nodes[i]) - } else { - rect.x = Math.min(rect.x, _rect.x) - rect.y = Math.min(rect.y, _rect.y) - rect.endX = Math.max(rect.endX, _rect.x + _rect.width) - rect.endY = Math.max(rect.endY, _rect.y + _rect.height) - } - } - if (rect == null) { - return - } - rect.width = rect.endX - rect.x - rect.height = rect.endY - rect.y - let fontSize = +nodeStyle.fontSize.replace('px', '') - let textarea = document.getElementById('textarea_' + rId) - if (textarea) { - textarea.remove() - } - textarea = document.createElement('textarea') - textarea.id = 'textarea_' + rId - textarea.style.position = 'absolute' - textarea.style.background = 'none' - textarea.style.border = 'none' - textarea.style.padding = '0' - textarea.style.margin = '0' - textarea.style.resize = 'none' - textarea.style.overflow = 'hidden' - textarea.style.outline = 'none' - textarea.style.zIndex = 999 - let scrollY = window.scrollY || document.documentElement.scrollTop - let scrollX = window.scrollX || document.documentElement.scrollLeft - textarea.style.left = (rect.x + scrollX) + 'px' - textarea.style.top = (rect.y + scrollY) + 'px' - let textWordWrap = textObj.extInfo.property.textWordWrap ?? true - textarea.style.width = Math.max(scaleValue(textObj.point[2]) || rect.width, fontSize) + 'px' - textarea.style.height = Math.max(scaleValue(textObj.point[3]) || rect.height, fontSize) + 'px' - let rotation = (textObj.extInfo.property || {}).rotation - if (rotation) { - textarea.style.transformOrigin = 'center' - textarea.style.transform = 'rotate(' + rotation + 'deg)' - } - if (nodeStyle.fill && nodeStyle.fill.startsWith('rgb')) { - textarea.style.color = nodeStyle.fill - } - textarea.style.font = nodeStyle.font - textarea.style.fontSize = fontSize + 'px' - let p_property = textObj.children[0]?.extInfo.property - // let lineSpacing = p_property.lineSpacing > 0 ? (p_property.lineSpacing / 100) : (1 + Math.abs(p_property.lineSpacing || 0) / 100) - // if (lineSpacing && lineSpacing != 1) { - // textarea.style.lineHeight = lineSpacing - // } - textarea.value = obj.text - nodes.forEach(s => s.style.visibility = 'hidden') - document.body.appendChild(textarea) - textarea.addEventListener('blur', function () { - if (obj.text == textarea.value) { - textarea.remove() - nodes.forEach(s => s.style.visibility = null) - return - } - obj.text = textarea.value - recursion(textObj.children, c => { - if (c.id == rId) { - c.text = obj.text - } - }) - textarea.remove() - let gNode = document.getElementById('g-' + textObj.id) - let g = d3.select(gNode) - drawTextWithG(g, textObj) - if ($this.onchange) { - $this.onchange(textObj) - } - }) - textarea.addEventListener('focus', function () { - if (textarea.scrollHeight > textarea.clientHeight) { - if (textWordWrap) { - textarea.style.height = textarea.scrollHeight + 'px' - } else { - textarea.style.width = textarea.clientWidth + fontSize + 'px' - } - } else if (textarea.scrollWidth > textarea.clientWidth) { - if (textWordWrap) { - textarea.style.height = textarea.clientWidth + fontSize + 'px' - } else { - textarea.style.width = textarea.scrollWidth + 'px' - } - } - }) - textarea.addEventListener('input', function () { - if (textarea.scrollHeight > textarea.clientHeight) { - if (textWordWrap) { - textarea.style.height = textarea.scrollHeight + 'px' - if (textObj.extInfo.property.textVerticalAlignment == 'BOTTOM') { - textarea.style.top = +textarea.style.top.replace('px', '') - fontSize + 'px' - } else if (textObj.extInfo.property.textVerticalAlignment == 'MIDDLE') { - textarea.style.top = +textarea.style.top.replace('px', '') - fontSize / 2 + 'px' - } - } else { - textarea.style.width = textarea.clientWidth + fontSize + 'px' - if (p_property.textAlign == 'RIGHT') { - textarea.style.left = +textarea.style.left.replace('px', '') - fontSize + 'px' - } else if (p_property.textAlign == 'CENTER') { - textarea.style.left = +textarea.style.left.replace('px', '') - fontSize / 2 + 'px' - } - } - } else if (textarea.scrollWidth > textarea.clientWidth) { - if (!textWordWrap) { - textarea.style.width = textarea.scrollWidth + 'px' - if (p_property.textAlign == 'RIGHT') { - textarea.style.left = +textarea.style.left.replace('px', '') - fontSize + 'px' - } else if (p_property.textAlign == 'CENTER') { - textarea.style.left = +textarea.style.left.replace('px', '') - fontSize / 2 + 'px' - } - } - } - }) - textarea.focus() - } - - this.idMap = idMap - this.recursion = recursion - this.drawGeometry = drawGeometry - this.drawElement = drawElement - this.toPaint = toPaint - this.toColor = toColor - this.toColorValue = toColorValue - this.loadImage = loadImage - this.text = text - this.scaleValue = scaleValue - this.showPoint = showPoint - this.removePoint = removePoint - this.addElementMoveScale = addElementMoveScale - this.removeElementMoveScale = removeElementMoveScale - - d3.addEventListener('document', 'mousemove', function(event) { - if (!pptx) { - removePoint() - return - } - let svgNode = svg.node() - let svgRect = svgNode.getClientRects()[0] - if (!svgRect) { - return - } - let clientX = event.clientX - let clientY = event.clientY - if (!(clientX >= svgRect.x && clientX <= svgRect.x + svgRect.width && clientY >= svgRect.y && clientY <= svgRect.y + svgRect.height)) { - removePoint() - return - } - let offsetX = clientX - svgRect.x - let offsetY = clientY - svgRect.y - mTimer && clearTimeout(mTimer) - mTimer = setTimeout(() => { - let newPointList = [] - for (let i = 0; i < pointList.length; i++) { - let point = pointList[i] - if (offsetX >= point.x && offsetX <= point.endX && offsetY >= point.y && offsetY <= point.endY) { - // if (currentPoint == point) return - // showPoint(point) - // return - newPointList.push(point) - } - } - if (newPointList.length > 0) { - newPointList.sort((p1, p2) => { - let text1 = p1.obj.type == 'text' || p1.obj.type == 'freeform' - let text2 = p2.obj.type == 'text' || p2.obj.type == 'freeform' - if (!text1 && !text2) { - return 0 - } - let s1 = text(p1.obj) - let s2 = text(p2.obj) - if (s1 && s2) { - return 0 - } - if (s1) { - return -1 - } - if (s2) { - return 1 - } - return 0 - }) - showPoint(newPointList[0]) - } else { - removePoint() - } - }, 10) - }) - d3.addEventListener('document', 'keydown', function (event) { - if (!currentPoint) { - return - } - let obj = currentPoint.obj - if (!obj.point || obj.type == 'tableColumn') { - return - } - let gNode = document.getElementById('g-' + obj.id) - if (!gNode) { - return - } - if (event.keyCode == 46) { - recursion(page.children, element => { - if (obj.id == element.id) { - const children = element.pid ? idMap[element.pid].children : page.children - for (let i = 0; i < children.length; i++) { - if (children[i].id == element.id) { - children.splice(i, 1) - delete idMap[obj.id] - gNode.remove() - currentPoint = null - removeElementMoveScale() - calcPointList(page) - if ($this.onchange) { - $this.onchange(page, 'delete', obj, event) - } - break - } - } - } - }) - } - }) - d3.addEventListener('window', 'scroll', function() { - removePoint() - removeElementMoveScale() - }) - d3.addEventListener('window', 'resize', function() { - removePoint() - removeElementMoveScale() - page && calcPointList(page) - }) -} - -export { D3Element, d3, Ppt2Svg } \ No newline at end of file diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js deleted file mode 100644 index cfb7765..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/src/utils/sse.js +++ /dev/null @@ -1,238 +0,0 @@ -function SSE(url, options) { - this.INITIALIZING = -1; - this.CONNECTING = 0; - this.OPEN = 1; - this.CLOSED = 2; - - this.url = url; - - options = options || {}; - this.headers = options.headers || {}; - this.payload = options.payload !== undefined ? options.payload : ""; - this.method = options.method || (this.payload && "POST") || "GET"; - this.withCredentials = !!options.withCredentials; - - this.FIELD_SEPARATOR = ":"; - this.listeners = {}; - - this.xhr = null; - this.readyState = this.INITIALIZING; - this.progress = 0; - this.chunk = ""; - - this.addEventListener = function (type, listener) { - if (this.listeners[type] === undefined) { - this.listeners[type] = []; - } - - if (this.listeners[type].indexOf(listener) === -1) { - this.listeners[type].push(listener); - } - }; - - this.removeEventListener = function (type, listener) { - if (this.listeners[type] === undefined) { - return; - } - - var filtered = []; - this.listeners[type].forEach(function (element) { - if (element !== listener) { - filtered.push(element); - } - }); - if (filtered.length === 0) { - delete this.listeners[type]; - } else { - this.listeners[type] = filtered; - } - }; - - this.dispatchEvent = function (e) { - if (!e) { - return true; - } - - e.source = this; - - var onHandler = "on" + e.type; - if (Object.prototype.hasOwnProperty.call(this, onHandler)) { - this[onHandler].call(this, e); - if (e.defaultPrevented) { - return false; - } - } - - if (this.listeners[e.type]) { - return this.listeners[e.type].every(function (callback) { - callback(e); - return !e.defaultPrevented; - }); - } - - return true; - }; - - this._setReadyState = function (state) { - var event = new CustomEvent("readystatechange"); - event.readyState = state; - this.readyState = state; - this.dispatchEvent(event); - }; - - this._onStreamFailure = function (e) { - var event = new CustomEvent("error"); - event.data = e.currentTarget.response; - this.dispatchEvent(event); - this.close(); - }; - - this._onStreamAbort = function () { - this.dispatchEvent(new CustomEvent("abort")); - this.close(); - }; - - this._onStreamProgress = function (e) { - if (!this.xhr) { - return; - } - - if (this.xhr.status !== 200) { - this._onStreamFailure(e); - return; - } - - if (this.readyState == this.CONNECTING) { - this.dispatchEvent(new CustomEvent("open")); - this._setReadyState(this.OPEN); - } - - var data = this.xhr.responseText.substring(this.progress); - this.progress += data.length; - data.split(/(\r\n|\r|\n){2}/g).forEach( - function (part) { - if (part.trim().length === 0) { - this.dispatchEvent(this._parseEventChunk(this.chunk.trim())); - this.chunk = ""; - } else { - this.chunk += part; - } - }.bind(this) - ); - }; - - this._onStreamLoaded = function (e) { - this._onStreamProgress(e); - - // Parse the last chunk. - this.dispatchEvent(this._parseEventChunk(this.chunk)); - this.chunk = ""; - }; - - /** - * Parse a received SSE event chunk into a constructed event object. - */ - this._parseEventChunk = function (chunk) { - if (!chunk || chunk.length === 0) { - return null; - } - - var e = { id: null, retry: null, data: "", event: "message" }; - chunk.split(/\n|\r\n|\r/).forEach( - function (line) { - line = line.trimRight(); - var index = line.indexOf(this.FIELD_SEPARATOR); - if (index <= 0) { - // Line was either empty, or started with a separator and is a comment. - // Either way, ignore. - return; - } - - var field = line.substring(0, index); - if (!(field in e)) { - return; - } - - var value = line.substring(index + 1).trimLeft(); - if (field === "data") { - e[field] += value; - } else { - e[field] = value; - } - }.bind(this) - ); - - var event = new CustomEvent(e.event); - event.data = e.data; - event.id = e.id; - return event; - }; - - this._checkStreamClosed = function () { - if (!this.xhr) { - return; - } - - if (this.xhr.readyState === XMLHttpRequest.DONE) { - this._setReadyState(this.CLOSED); - var event = new CustomEvent("end"); - event.data = this.xhr.responseText; - this.dispatchEvent(event); - } - }; - - this.stream = function () { - this._setReadyState(this.CONNECTING); - - this.xhr = new XMLHttpRequest(); - this.xhr.addEventListener("progress", this._onStreamProgress.bind(this)); - this.xhr.addEventListener("load", this._onStreamLoaded.bind(this)); - this.xhr.addEventListener( - "readystatechange", - this._checkStreamClosed.bind(this) - ); - this.xhr.addEventListener("error", this._onStreamFailure.bind(this)); - this.xhr.addEventListener("abort", this._onStreamAbort.bind(this)); - this.xhr.open(this.method, this.url); - for (var header in this.headers) { - this.xhr.setRequestHeader(header, this.headers[header]); - } - this.xhr.withCredentials = this.withCredentials; - this.xhr.send(this.payload); - }; - - this.close = function () { - if (this.readyState === this.CLOSED) { - return; - } - - this.xhr.abort(); - this.xhr = null; - this._setReadyState(this.CLOSED); - }; -} - -export { SSE }; - -/* -const url = 'https://xxx/chat'; -var source = new SSE(url, { - method: 'POST', - // withCredentials: true, - headers: { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-cache' - }, - payload: JSON.stringify({ prompt: 'xxx' }), -}); -source.onmessage = function (data) { - console.log('chunk => ' + data.data) -}; -source.onend = function (data) { - console.log('结束'); -}; -source.onerror = function (err) { - console.error('异常', err); -}; -source.stream(); -*/ diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json deleted file mode 100644 index bde5b54..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.app.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "@vue/tsconfig/tsconfig.dom.json", - "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], - "exclude": ["src/**/__tests__/*"], - "compilerOptions": { - "allowJs": true, - "noImplicitAny": false, - "composite": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - - "baseUrl": ".", - "paths": { - "@/*": ["./src/*"] - } - } -} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json deleted file mode 100644 index 83e5fac..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "files": [], - "references": [ - { - "path": "./tsconfig.node.json" - }, - { - "path": "./tsconfig.app.json" - } - ], - "compilerOptions": { - "allowJs": true, - "noImplicitAny": false, - "target": "ESNext" - } -} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json deleted file mode 100644 index 590171b..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/tsconfig.node.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "@tsconfig/node20/tsconfig.json", - "include": [ - "vite.config.*", - "vitest.config.*", - "cypress.config.*", - "nightwatch.conf.*", - "playwright.config.*" - ], - "compilerOptions": { - "allowJs": true, - "noImplicitAny": false, - "composite": true, - "noEmit": true, - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - - "module": "ESNext", - "moduleResolution": "Bundler", - "types": ["node"] - } -} diff --git a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts b/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts deleted file mode 100644 index 5c45e1d..0000000 --- a/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398 (3)/aippt-vue-c9bc73c815bb02ad77d84e2d8fa5f52abc892398/vite.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { fileURLToPath, URL } from 'node:url' - -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - vue(), - ], - resolve: { - alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)) - } - } -})