lpdfio-lpdf 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lpdfio_lpdf-0.0.1/.gitignore +30 -0
- lpdfio_lpdf-0.0.1/LICENSE +131 -0
- lpdfio_lpdf-0.0.1/PKG-INFO +146 -0
- lpdfio_lpdf-0.0.1/lpdf/__init__.py +83 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/__init__.py +35 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/canvas_node.py +11 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/circle_node.py +24 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/clip.py +12 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/ellipse_node.py +28 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/image_node.py +24 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/layer_node.py +38 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/layer_options.py +14 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/line_cap.py +7 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/line_join.py +7 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/line_node.py +29 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/path_node.py +25 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/rect_node.py +29 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/run.py +22 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/styles.py +43 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/text_align.py +8 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/text_node.py +40 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/text_style.py +15 -0
- lpdfio_lpdf-0.0.1/lpdf/canvas/transform.py +28 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/__init__.py +14 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/encrypt_options.py +31 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/engine_exception.py +2 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/engine_options.py +11 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/render_options.py +12 -0
- lpdfio_lpdf-0.0.1/lpdf/engine/wasm_runner.py +32 -0
- lpdfio_lpdf-0.0.1/lpdf/engine.py +227 -0
- lpdfio_lpdf-0.0.1/lpdf/exceptions.py +2 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/__init__.py +21 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/document.py +22 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/document_meta.py +15 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/document_options.py +16 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/document_tokens.py +19 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/orientation.py +6 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/section_canvas.py +16 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/section_layout.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/section_node.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/kit/section_options.py +12 -0
- lpdfio_lpdf-0.0.1/lpdf/kit.py +129 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/__init__.py +41 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/barcode_node.py +16 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/barcode_options.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/cluster_options.py +17 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/container_node.py +20 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/divider_node.py +16 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/divider_options.py +10 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/field_node.py +22 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/field_options.py +23 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/field_type.py +9 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/flank_options.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/frame_options.py +15 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/grid_options.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/img_node.py +16 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/img_options.py +19 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/link_options.py +10 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/node.py +11 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/pin.py +8 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/region_node.py +21 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/region_options.py +10 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/span_node.py +18 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/span_options.py +14 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/split_options.py +17 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/stack_options.py +17 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/table_options.py +17 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/td_options.py +15 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/text_node.py +19 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/text_options.py +20 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/thead_options.py +8 -0
- lpdfio_lpdf-0.0.1/lpdf/layout/tr_options.py +8 -0
- lpdfio_lpdf-0.0.1/lpdf/lpdf_canvas.py +68 -0
- lpdfio_lpdf-0.0.1/lpdf/lpdf_engine.py +202 -0
- lpdfio_lpdf-0.0.1/lpdf/lpdf_kit.py +50 -0
- lpdfio_lpdf-0.0.1/lpdf/lpdf_layout.py +129 -0
- lpdfio_lpdf-0.0.1/lpdf/options.py +13 -0
- lpdfio_lpdf-0.0.1/lpdf/shared/__init__.py +4 -0
- lpdfio_lpdf-0.0.1/lpdf/shared/attrs_helper.py +31 -0
- lpdfio_lpdf-0.0.1/lpdf/shared/page_scope.py +6 -0
- lpdfio_lpdf-0.0.1/lpdf/types.py +396 -0
- lpdfio_lpdf-0.0.1/lpdf/wasm_runner.py +32 -0
- lpdfio_lpdf-0.0.1/pyproject.toml +26 -0
- lpdfio_lpdf-0.0.1/resources/lpdf-wasi.wasm +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.egg-info/
|
|
11
|
+
*.egg
|
|
12
|
+
.eggs/
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# Testing
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# Editors
|
|
25
|
+
.vscode/
|
|
26
|
+
.idea/
|
|
27
|
+
|
|
28
|
+
# OS
|
|
29
|
+
.DS_Store
|
|
30
|
+
Thumbs.db
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# LPDF License
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Codesense LLC
|
|
4
|
+
License inquiries: license@lpdf.io
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Choosing Your License
|
|
9
|
+
|
|
10
|
+
LPDF is available under two license types: a free Community License for individuals and qualifying organizations, and paid licenses for larger commercial use. All license tiers receive the complete feature set — no capabilities are gated behind paid plans.
|
|
11
|
+
|
|
12
|
+
### Equal Features Across All Tiers
|
|
13
|
+
|
|
14
|
+
Every user of LPDF, regardless of license tier, has access to the same library, the same layout engine, the same adapters, and the same output quality. Licensing determines the terms of use, not the features available.
|
|
15
|
+
|
|
16
|
+
### Transitive Dependency
|
|
17
|
+
|
|
18
|
+
If LPDF is pulled in as an indirect dependency of another library or framework rather than used directly in your project, the Community License applies automatically, regardless of your organization's revenue.
|
|
19
|
+
|
|
20
|
+
This exemption does not apply if the dependency was introduced, created, or controlled by the licensee's organization for the purpose of circumventing license requirements.
|
|
21
|
+
|
|
22
|
+
### Individuals and Open-Source Projects
|
|
23
|
+
|
|
24
|
+
Personal use and open-source projects whose source code is publicly available under an OSI-approved license qualify for the Community License at no cost.
|
|
25
|
+
|
|
26
|
+
### Non-Profit Organizations
|
|
27
|
+
|
|
28
|
+
Legally recognized non-profit organizations (including 501(c)(3) entities in the United States and equivalent status in other jurisdictions) qualify for the Community License regardless of operating budget.
|
|
29
|
+
|
|
30
|
+
### Small Businesses
|
|
31
|
+
|
|
32
|
+
Companies and organizations whose total annual gross revenue did not exceed **1,000,000 USD** in the most recent 12-month fiscal year qualify for the Community License at no cost, including for commercial products and services.
|
|
33
|
+
|
|
34
|
+
Organizations whose revenue crosses the 1,000,000 USD threshold have a **90-day grace period** following the close of their fiscal year to obtain a Professional or Enterprise license. During this grace period, continued use is permitted.
|
|
35
|
+
|
|
36
|
+
### Larger Businesses
|
|
37
|
+
|
|
38
|
+
Companies and organizations whose total annual gross revenue exceeded **1,000,000 USD** in the most recent 12-month fiscal year must obtain a Professional or Enterprise license to use LPDF in production environments.
|
|
39
|
+
|
|
40
|
+
"Production environment" means any environment in which the Software processes real user data or supports live business operations, including staging environments accessible by end users.
|
|
41
|
+
|
|
42
|
+
- **Professional License** — for organizations with up to 10 developers using LPDF
|
|
43
|
+
- **Enterprise License** — for organizations with more than 10 developers using LPDF
|
|
44
|
+
|
|
45
|
+
"Developer" means any individual who writes, modifies, or reviews code that directly integrates or calls the Software's API, including but not limited to software engineers and technical leads. The term does not include QA engineers whose sole interaction is executing pre-written test suites, or DevOps engineers whose sole interaction is deploying pre-packaged artifacts.
|
|
46
|
+
|
|
47
|
+
### Supporting LPDF
|
|
48
|
+
|
|
49
|
+
Paid licenses directly fund the continued development, maintenance, and improvement of LPDF. If your organization has grown beyond the Community threshold, purchasing a license is the most direct way to ensure LPDF continues to exist and improve.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## LPDF Community License
|
|
54
|
+
|
|
55
|
+
*Applies to: individuals, open-source projects, non-profit organizations, and companies with annual gross revenue under 1,000,000 USD.*
|
|
56
|
+
|
|
57
|
+
Permission is hereby granted, free of charge, to any person or qualifying organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
58
|
+
|
|
59
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
60
|
+
|
|
61
|
+
All modifications to the Software made by the licensee remain the intellectual property of the licensee. Codesense LLC claims no ownership over modifications unless they are voluntarily submitted as contributions to the LPDF project under a separate Contributor License Agreement.
|
|
62
|
+
|
|
63
|
+
If your organization's annual gross revenue exceeds 1,000,000 USD, your rights under this Community License are automatically terminated upon expiration of the 90-day grace period described above, and you must obtain a Professional or Enterprise license before continuing to use LPDF in production.
|
|
64
|
+
|
|
65
|
+
### Disclaimer of Warranty
|
|
66
|
+
|
|
67
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL CODESENSE LLC OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN NO EVENT SHALL CODESENSE LLC'S TOTAL CUMULATIVE LIABILITY TO ANY PARTY EXCEED THE GREATER OF (A) THE FEES PAID BY THAT PARTY TO CODESENSE LLC IN THE TWELVE MONTHS PRECEDING THE CLAIM, OR (B) ONE HUNDRED US DOLLARS (USD 100).
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## LPDF Professional and Enterprise License
|
|
72
|
+
|
|
73
|
+
*Applies to: companies and organizations with annual gross revenue exceeding 1,000,000 USD.*
|
|
74
|
+
|
|
75
|
+
### Conduct
|
|
76
|
+
|
|
77
|
+
Licensees agree not to make false statements of fact about LPDF, Codesense LLC, or its contributors that are intended to cause material harm to the reputation of the project or the company. This clause does not restrict good-faith criticism, bug reports, public discussion of software deficiencies, or reviews based on the licensee's genuine experience.
|
|
78
|
+
|
|
79
|
+
License rights may not be rented, leased, or transferred to any third party.
|
|
80
|
+
|
|
81
|
+
### License Grant
|
|
82
|
+
|
|
83
|
+
Subject to payment of the applicable license fee, Codesense LLC grants the licensee a non-exclusive, worldwide, royalty-free license to:
|
|
84
|
+
|
|
85
|
+
- Use, copy, modify, and integrate the Software into unlimited applications and projects
|
|
86
|
+
- Distribute the Software as part of compiled or packaged commercial products
|
|
87
|
+
- Deploy the Software across unlimited servers, environments, and infrastructure
|
|
88
|
+
|
|
89
|
+
**Professional License** grants these rights to up to 10 developers (as defined above) within the licensee's organization.
|
|
90
|
+
|
|
91
|
+
**Enterprise License** grants these rights to all developers within the licensee's organization with no developer-count limit.
|
|
92
|
+
|
|
93
|
+
### License Fees and Evaluation
|
|
94
|
+
|
|
95
|
+
A license fee is required for use of LPDF in production environments (as defined above). Evaluation and testing in non-production environments is permitted without a license for a period not exceeding 30 days.
|
|
96
|
+
|
|
97
|
+
Upon payment, the licensee receives a perpetual license for the version of LPDF current at the time of purchase, plus one year of updates, new features, and security patches. Continued access to new versions after the first year requires annual renewal. Cancellation of renewal does not affect the perpetual license for the version already held.
|
|
98
|
+
|
|
99
|
+
### Ownership and Modifications
|
|
100
|
+
|
|
101
|
+
Codesense LLC retains all ownership, copyright, and intellectual property rights in the Software at all times. This license grants rights to use the Software; it does not transfer ownership of any kind.
|
|
102
|
+
|
|
103
|
+
All modifications to the Software made by the licensee remain the intellectual property of the licensee. Codesense LLC claims no ownership over licensee modifications unless they are voluntarily submitted as contributions to the LPDF project under a separate Contributor License Agreement.
|
|
104
|
+
|
|
105
|
+
### Copyright
|
|
106
|
+
|
|
107
|
+
All copies, modifications, and distributions of the Software must retain the original copyright notice. Licensees may not remove, alter, or obscure any copyright, trademark, or attribution notices included in the Software.
|
|
108
|
+
|
|
109
|
+
### Data and Privacy
|
|
110
|
+
|
|
111
|
+
Codesense LLC does not collect, process, or retain any data that the licensee processes through the Software. All data processed by LPDF remains solely within the licensee's infrastructure. For more information, see the Codesense LLC Privacy Policy at lpdf.io/privacy.
|
|
112
|
+
|
|
113
|
+
### Export Compliance
|
|
114
|
+
|
|
115
|
+
The Software may be subject to export control laws and regulations, including the U.S. Export Administration Regulations (EAR) and sanctions programs administered by OFAC. The licensee is solely responsible for complying with all applicable export control and sanctions laws in connection with the licensee's use of the Software.
|
|
116
|
+
|
|
117
|
+
### Disclaimer of Warranty
|
|
118
|
+
|
|
119
|
+
THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL CODESENSE LLC OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN NO EVENT SHALL CODESENSE LLC'S TOTAL CUMULATIVE LIABILITY TO ANY PARTY EXCEED THE GREATER OF (A) THE FEES PAID BY THAT PARTY TO CODESENSE LLC IN THE TWELVE MONTHS PRECEDING THE CLAIM, OR (B) ONE HUNDRED US DOLLARS (USD 100).
|
|
120
|
+
|
|
121
|
+
### Governing Law and Dispute Resolution
|
|
122
|
+
|
|
123
|
+
This license is governed by and construed in accordance with the laws of the State of Delaware, United States, without regard to its conflict of law provisions.
|
|
124
|
+
|
|
125
|
+
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in **Plano, Texas**. Judgment on the award rendered by the arbitrator may be entered in any court of competent jurisdiction.
|
|
126
|
+
|
|
127
|
+
Notwithstanding the foregoing, either party may seek injunctive or other equitable relief in any court of competent jurisdiction to prevent the actual or threatened infringement, misappropriation, or violation of a party's intellectual property rights.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
For license purchases and inquiries: **license@lpdf.io** | lpdf.io/privacy
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lpdfio-lpdf
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Python adapter for lpdf — pixel-perfect, lightweight, and consistent PDF rendering
|
|
5
|
+
Project-URL: Homepage, https://lpdf.io
|
|
6
|
+
Project-URL: Repository, https://github.com/lpdfio/lpdf-python
|
|
7
|
+
Project-URL: Changelog, https://github.com/lpdfio/lpdf/releases
|
|
8
|
+
Author-email: "lpdf.io" <support@lpdf.io>
|
|
9
|
+
License: # LPDF License
|
|
10
|
+
|
|
11
|
+
Copyright © 2026 Codesense LLC
|
|
12
|
+
License inquiries: license@lpdf.io
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Choosing Your License
|
|
17
|
+
|
|
18
|
+
LPDF is available under two license types: a free Community License for individuals and qualifying organizations, and paid licenses for larger commercial use. All license tiers receive the complete feature set — no capabilities are gated behind paid plans.
|
|
19
|
+
|
|
20
|
+
### Equal Features Across All Tiers
|
|
21
|
+
|
|
22
|
+
Every user of LPDF, regardless of license tier, has access to the same library, the same layout engine, the same adapters, and the same output quality. Licensing determines the terms of use, not the features available.
|
|
23
|
+
|
|
24
|
+
### Transitive Dependency
|
|
25
|
+
|
|
26
|
+
If LPDF is pulled in as an indirect dependency of another library or framework rather than used directly in your project, the Community License applies automatically, regardless of your organization's revenue.
|
|
27
|
+
|
|
28
|
+
This exemption does not apply if the dependency was introduced, created, or controlled by the licensee's organization for the purpose of circumventing license requirements.
|
|
29
|
+
|
|
30
|
+
### Individuals and Open-Source Projects
|
|
31
|
+
|
|
32
|
+
Personal use and open-source projects whose source code is publicly available under an OSI-approved license qualify for the Community License at no cost.
|
|
33
|
+
|
|
34
|
+
### Non-Profit Organizations
|
|
35
|
+
|
|
36
|
+
Legally recognized non-profit organizations (including 501(c)(3) entities in the United States and equivalent status in other jurisdictions) qualify for the Community License regardless of operating budget.
|
|
37
|
+
|
|
38
|
+
### Small Businesses
|
|
39
|
+
|
|
40
|
+
Companies and organizations whose total annual gross revenue did not exceed **1,000,000 USD** in the most recent 12-month fiscal year qualify for the Community License at no cost, including for commercial products and services.
|
|
41
|
+
|
|
42
|
+
Organizations whose revenue crosses the 1,000,000 USD threshold have a **90-day grace period** following the close of their fiscal year to obtain a Professional or Enterprise license. During this grace period, continued use is permitted.
|
|
43
|
+
|
|
44
|
+
### Larger Businesses
|
|
45
|
+
|
|
46
|
+
Companies and organizations whose total annual gross revenue exceeded **1,000,000 USD** in the most recent 12-month fiscal year must obtain a Professional or Enterprise license to use LPDF in production environments.
|
|
47
|
+
|
|
48
|
+
"Production environment" means any environment in which the Software processes real user data or supports live business operations, including staging environments accessible by end users.
|
|
49
|
+
|
|
50
|
+
- **Professional License** — for organizations with up to 10 developers using LPDF
|
|
51
|
+
- **Enterprise License** — for organizations with more than 10 developers using LPDF
|
|
52
|
+
|
|
53
|
+
"Developer" means any individual who writes, modifies, or reviews code that directly integrates or calls the Software's API, including but not limited to software engineers and technical leads. The term does not include QA engineers whose sole interaction is executing pre-written test suites, or DevOps engineers whose sole interaction is deploying pre-packaged artifacts.
|
|
54
|
+
|
|
55
|
+
### Supporting LPDF
|
|
56
|
+
|
|
57
|
+
Paid licenses directly fund the continued development, maintenance, and improvement of LPDF. If your organization has grown beyond the Community threshold, purchasing a license is the most direct way to ensure LPDF continues to exist and improve.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## LPDF Community License
|
|
62
|
+
|
|
63
|
+
*Applies to: individuals, open-source projects, non-profit organizations, and companies with annual gross revenue under 1,000,000 USD.*
|
|
64
|
+
|
|
65
|
+
Permission is hereby granted, free of charge, to any person or qualifying organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
66
|
+
|
|
67
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
68
|
+
|
|
69
|
+
All modifications to the Software made by the licensee remain the intellectual property of the licensee. Codesense LLC claims no ownership over modifications unless they are voluntarily submitted as contributions to the LPDF project under a separate Contributor License Agreement.
|
|
70
|
+
|
|
71
|
+
If your organization's annual gross revenue exceeds 1,000,000 USD, your rights under this Community License are automatically terminated upon expiration of the 90-day grace period described above, and you must obtain a Professional or Enterprise license before continuing to use LPDF in production.
|
|
72
|
+
|
|
73
|
+
### Disclaimer of Warranty
|
|
74
|
+
|
|
75
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL CODESENSE LLC OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN NO EVENT SHALL CODESENSE LLC'S TOTAL CUMULATIVE LIABILITY TO ANY PARTY EXCEED THE GREATER OF (A) THE FEES PAID BY THAT PARTY TO CODESENSE LLC IN THE TWELVE MONTHS PRECEDING THE CLAIM, OR (B) ONE HUNDRED US DOLLARS (USD 100).
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## LPDF Professional and Enterprise License
|
|
80
|
+
|
|
81
|
+
*Applies to: companies and organizations with annual gross revenue exceeding 1,000,000 USD.*
|
|
82
|
+
|
|
83
|
+
### Conduct
|
|
84
|
+
|
|
85
|
+
Licensees agree not to make false statements of fact about LPDF, Codesense LLC, or its contributors that are intended to cause material harm to the reputation of the project or the company. This clause does not restrict good-faith criticism, bug reports, public discussion of software deficiencies, or reviews based on the licensee's genuine experience.
|
|
86
|
+
|
|
87
|
+
License rights may not be rented, leased, or transferred to any third party.
|
|
88
|
+
|
|
89
|
+
### License Grant
|
|
90
|
+
|
|
91
|
+
Subject to payment of the applicable license fee, Codesense LLC grants the licensee a non-exclusive, worldwide, royalty-free license to:
|
|
92
|
+
|
|
93
|
+
- Use, copy, modify, and integrate the Software into unlimited applications and projects
|
|
94
|
+
- Distribute the Software as part of compiled or packaged commercial products
|
|
95
|
+
- Deploy the Software across unlimited servers, environments, and infrastructure
|
|
96
|
+
|
|
97
|
+
**Professional License** grants these rights to up to 10 developers (as defined above) within the licensee's organization.
|
|
98
|
+
|
|
99
|
+
**Enterprise License** grants these rights to all developers within the licensee's organization with no developer-count limit.
|
|
100
|
+
|
|
101
|
+
### License Fees and Evaluation
|
|
102
|
+
|
|
103
|
+
A license fee is required for use of LPDF in production environments (as defined above). Evaluation and testing in non-production environments is permitted without a license for a period not exceeding 30 days.
|
|
104
|
+
|
|
105
|
+
Upon payment, the licensee receives a perpetual license for the version of LPDF current at the time of purchase, plus one year of updates, new features, and security patches. Continued access to new versions after the first year requires annual renewal. Cancellation of renewal does not affect the perpetual license for the version already held.
|
|
106
|
+
|
|
107
|
+
### Ownership and Modifications
|
|
108
|
+
|
|
109
|
+
Codesense LLC retains all ownership, copyright, and intellectual property rights in the Software at all times. This license grants rights to use the Software; it does not transfer ownership of any kind.
|
|
110
|
+
|
|
111
|
+
All modifications to the Software made by the licensee remain the intellectual property of the licensee. Codesense LLC claims no ownership over licensee modifications unless they are voluntarily submitted as contributions to the LPDF project under a separate Contributor License Agreement.
|
|
112
|
+
|
|
113
|
+
### Copyright
|
|
114
|
+
|
|
115
|
+
All copies, modifications, and distributions of the Software must retain the original copyright notice. Licensees may not remove, alter, or obscure any copyright, trademark, or attribution notices included in the Software.
|
|
116
|
+
|
|
117
|
+
### Data and Privacy
|
|
118
|
+
|
|
119
|
+
Codesense LLC does not collect, process, or retain any data that the licensee processes through the Software. All data processed by LPDF remains solely within the licensee's infrastructure. For more information, see the Codesense LLC Privacy Policy at lpdf.io/privacy.
|
|
120
|
+
|
|
121
|
+
### Export Compliance
|
|
122
|
+
|
|
123
|
+
The Software may be subject to export control laws and regulations, including the U.S. Export Administration Regulations (EAR) and sanctions programs administered by OFAC. The licensee is solely responsible for complying with all applicable export control and sanctions laws in connection with the licensee's use of the Software.
|
|
124
|
+
|
|
125
|
+
### Disclaimer of Warranty
|
|
126
|
+
|
|
127
|
+
THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL CODESENSE LLC OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN NO EVENT SHALL CODESENSE LLC'S TOTAL CUMULATIVE LIABILITY TO ANY PARTY EXCEED THE GREATER OF (A) THE FEES PAID BY THAT PARTY TO CODESENSE LLC IN THE TWELVE MONTHS PRECEDING THE CLAIM, OR (B) ONE HUNDRED US DOLLARS (USD 100).
|
|
128
|
+
|
|
129
|
+
### Governing Law and Dispute Resolution
|
|
130
|
+
|
|
131
|
+
This license is governed by and construed in accordance with the laws of the State of Delaware, United States, without regard to its conflict of law provisions.
|
|
132
|
+
|
|
133
|
+
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in **Plano, Texas**. Judgment on the award rendered by the arbitrator may be entered in any court of competent jurisdiction.
|
|
134
|
+
|
|
135
|
+
Notwithstanding the foregoing, either party may seek injunctive or other equitable relief in any court of competent jurisdiction to prevent the actual or threatened infringement, misappropriation, or violation of a party's intellectual property rights.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
For license purchases and inquiries: **license@lpdf.io** | lpdf.io/privacy
|
|
140
|
+
License-File: LICENSE
|
|
141
|
+
Keywords: document,pdf,wasm,xml
|
|
142
|
+
Classifier: Development Status :: 4 - Beta
|
|
143
|
+
Classifier: Intended Audience :: Developers
|
|
144
|
+
Classifier: Programming Language :: Python :: 3
|
|
145
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
146
|
+
Requires-Python: >=3.8
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Top-level facades
|
|
2
|
+
from .lpdf_engine import LpdfEngine
|
|
3
|
+
from .lpdf_kit import LpdfKit
|
|
4
|
+
from .lpdf_layout import LpdfLayout
|
|
5
|
+
from .lpdf_canvas import LpdfCanvas
|
|
6
|
+
|
|
7
|
+
# engine subpackage — commonly used types
|
|
8
|
+
from .engine.engine_exception import EngineException
|
|
9
|
+
from .engine.engine_options import EngineOptions
|
|
10
|
+
from .engine.render_options import RenderOptions
|
|
11
|
+
from .engine.encrypt_options import EncryptOptions, EncryptPermissions
|
|
12
|
+
|
|
13
|
+
# kit subpackage
|
|
14
|
+
from .kit.document import Document
|
|
15
|
+
from .kit.document_options import DocumentOptions
|
|
16
|
+
from .kit.document_meta import DocumentMeta
|
|
17
|
+
from .kit.document_tokens import DocumentTokens
|
|
18
|
+
from .kit.section_node import SectionNode
|
|
19
|
+
from .kit.section_options import SectionOptions
|
|
20
|
+
from .kit.section_layout import SectionLayout
|
|
21
|
+
from .kit.section_canvas import SectionCanvas
|
|
22
|
+
from .kit.orientation import Orientation
|
|
23
|
+
|
|
24
|
+
# layout subpackage — options and enums
|
|
25
|
+
from .layout.pin import Pin
|
|
26
|
+
from .layout.field_type import FieldType
|
|
27
|
+
from .layout.stack_options import StackOptions
|
|
28
|
+
from .layout.flank_options import FlankOptions
|
|
29
|
+
from .layout.split_options import SplitOptions
|
|
30
|
+
from .layout.cluster_options import ClusterOptions
|
|
31
|
+
from .layout.grid_options import GridOptions
|
|
32
|
+
from .layout.frame_options import FrameOptions
|
|
33
|
+
from .layout.link_options import LinkOptions
|
|
34
|
+
from .layout.text_options import TextOptions
|
|
35
|
+
from .layout.span_options import SpanOptions
|
|
36
|
+
from .layout.divider_options import DividerOptions
|
|
37
|
+
from .layout.img_options import ImgOptions
|
|
38
|
+
from .layout.barcode_options import BarcodeOptions
|
|
39
|
+
from .layout.field_options import FieldOptions
|
|
40
|
+
from .layout.region_options import RegionOptions
|
|
41
|
+
from .layout.table_options import TableOptions
|
|
42
|
+
from .layout.thead_options import TheadOptions
|
|
43
|
+
from .layout.tr_options import TrOptions
|
|
44
|
+
from .layout.td_options import TdOptions
|
|
45
|
+
|
|
46
|
+
# canvas subpackage — commonly used types
|
|
47
|
+
from .canvas.layer_options import LayerOptions
|
|
48
|
+
from .canvas.transform import Transform
|
|
49
|
+
from .canvas.clip import Clip
|
|
50
|
+
from .canvas.run import Run
|
|
51
|
+
from .canvas.styles import RectStyle, LineStyle, EllipseStyle, PathStyle
|
|
52
|
+
from .canvas.text_style import TextStyle
|
|
53
|
+
from .canvas.text_align import TextAlign
|
|
54
|
+
from .canvas.line_cap import LineCap
|
|
55
|
+
from .canvas.line_join import LineJoin
|
|
56
|
+
|
|
57
|
+
# shared
|
|
58
|
+
from .shared.page_scope import PageScope
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
# facades
|
|
62
|
+
"LpdfEngine", "LpdfKit", "LpdfLayout", "LpdfCanvas",
|
|
63
|
+
# engine
|
|
64
|
+
"EngineException", "EngineOptions", "RenderOptions",
|
|
65
|
+
"EncryptOptions", "EncryptPermissions",
|
|
66
|
+
# kit
|
|
67
|
+
"Document", "DocumentOptions", "DocumentMeta", "DocumentTokens",
|
|
68
|
+
"SectionNode", "SectionOptions", "SectionLayout", "SectionCanvas",
|
|
69
|
+
"Orientation",
|
|
70
|
+
# layout options / enums
|
|
71
|
+
"Pin", "FieldType",
|
|
72
|
+
"StackOptions", "FlankOptions", "SplitOptions", "ClusterOptions",
|
|
73
|
+
"GridOptions", "FrameOptions", "LinkOptions",
|
|
74
|
+
"TextOptions", "SpanOptions", "DividerOptions",
|
|
75
|
+
"ImgOptions", "BarcodeOptions", "FieldOptions", "RegionOptions",
|
|
76
|
+
"TableOptions", "TheadOptions", "TrOptions", "TdOptions",
|
|
77
|
+
# canvas
|
|
78
|
+
"LayerOptions", "Transform", "Clip", "Run",
|
|
79
|
+
"RectStyle", "LineStyle", "EllipseStyle", "PathStyle",
|
|
80
|
+
"TextStyle", "TextAlign", "LineCap", "LineJoin",
|
|
81
|
+
# shared
|
|
82
|
+
"PageScope",
|
|
83
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .canvas_node import CanvasNode
|
|
2
|
+
from .layer_node import LayerNode
|
|
3
|
+
from .layer_options import LayerOptions
|
|
4
|
+
from .rect_node import RectNode
|
|
5
|
+
from .line_node import LineNode
|
|
6
|
+
from .ellipse_node import EllipseNode
|
|
7
|
+
from .circle_node import CircleNode
|
|
8
|
+
from .path_node import PathNode
|
|
9
|
+
from .text_node import CanvasTextNode
|
|
10
|
+
from .image_node import ImageNode
|
|
11
|
+
from .text_style import TextStyle
|
|
12
|
+
from .text_align import TextAlign
|
|
13
|
+
from .run import Run
|
|
14
|
+
from .transform import Transform
|
|
15
|
+
from .clip import Clip
|
|
16
|
+
from .line_cap import LineCap
|
|
17
|
+
from .line_join import LineJoin
|
|
18
|
+
from .styles import RectStyle, LineStyle, EllipseStyle, PathStyle
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CanvasNode",
|
|
22
|
+
"LayerNode", "LayerOptions",
|
|
23
|
+
"RectNode", "RectStyle",
|
|
24
|
+
"LineNode", "LineStyle",
|
|
25
|
+
"EllipseNode", "EllipseStyle",
|
|
26
|
+
"CircleNode",
|
|
27
|
+
"PathNode", "PathStyle",
|
|
28
|
+
"CanvasTextNode", "TextStyle", "TextAlign",
|
|
29
|
+
"Run",
|
|
30
|
+
"ImageNode",
|
|
31
|
+
"Transform",
|
|
32
|
+
"Clip",
|
|
33
|
+
"LineCap",
|
|
34
|
+
"LineJoin",
|
|
35
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .canvas_node import CanvasNode
|
|
4
|
+
from .styles import EllipseStyle
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CircleNode(CanvasNode):
|
|
8
|
+
__slots__ = ("_cx", "_cy", "_r", "_style")
|
|
9
|
+
|
|
10
|
+
def __init__(self, cx: float, cy: float, r: float, style: EllipseStyle | None = None):
|
|
11
|
+
self._cx = cx
|
|
12
|
+
self._cy = cy
|
|
13
|
+
self._r = r
|
|
14
|
+
self._style = style
|
|
15
|
+
|
|
16
|
+
def to_dict(self) -> dict:
|
|
17
|
+
attrs: dict = {"x": str(self._cx), "y": str(self._cy), "r": str(self._r)}
|
|
18
|
+
s = self._style
|
|
19
|
+
if s is not None:
|
|
20
|
+
if s.fill is not None: attrs["fill"] = s.fill
|
|
21
|
+
if s.stroke is not None: attrs["stroke"] = s.stroke
|
|
22
|
+
if s.stroke_width is not None: attrs["stroke-width"] = str(s.stroke_width)
|
|
23
|
+
if s.stroke_dash is not None: attrs["stroke-dash"] = " ".join(str(v) for v in s.stroke_dash)
|
|
24
|
+
return {"type": "canvas-circle", "attrs": attrs}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .canvas_node import CanvasNode
|
|
4
|
+
from .styles import EllipseStyle
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EllipseNode(CanvasNode):
|
|
8
|
+
__slots__ = ("_cx", "_cy", "_rx", "_ry", "_style")
|
|
9
|
+
|
|
10
|
+
def __init__(self, cx: float, cy: float, rx: float, ry: float, style: EllipseStyle | None = None):
|
|
11
|
+
self._cx = cx
|
|
12
|
+
self._cy = cy
|
|
13
|
+
self._rx = rx
|
|
14
|
+
self._ry = ry
|
|
15
|
+
self._style = style
|
|
16
|
+
|
|
17
|
+
def to_dict(self) -> dict:
|
|
18
|
+
attrs: dict = {
|
|
19
|
+
"x": str(self._cx), "y": str(self._cy),
|
|
20
|
+
"rx": str(self._rx), "ry": str(self._ry),
|
|
21
|
+
}
|
|
22
|
+
s = self._style
|
|
23
|
+
if s is not None:
|
|
24
|
+
if s.fill is not None: attrs["fill"] = s.fill
|
|
25
|
+
if s.stroke is not None: attrs["stroke"] = s.stroke
|
|
26
|
+
if s.stroke_width is not None: attrs["stroke-width"] = str(s.stroke_width)
|
|
27
|
+
if s.stroke_dash is not None: attrs["stroke-dash"] = " ".join(str(v) for v in s.stroke_dash)
|
|
28
|
+
return {"type": "canvas-ellipse", "attrs": attrs}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .canvas_node import CanvasNode
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ImageNode(CanvasNode):
|
|
7
|
+
__slots__ = ("_x", "_y", "_w", "_h", "_name")
|
|
8
|
+
|
|
9
|
+
def __init__(self, x: float, y: float, w: float, h: float, name: str):
|
|
10
|
+
self._x = x
|
|
11
|
+
self._y = y
|
|
12
|
+
self._w = w
|
|
13
|
+
self._h = h
|
|
14
|
+
self._name = name
|
|
15
|
+
|
|
16
|
+
def to_dict(self) -> dict:
|
|
17
|
+
return {
|
|
18
|
+
"type": "canvas-img",
|
|
19
|
+
"attrs": {
|
|
20
|
+
"x": str(self._x), "y": str(self._y),
|
|
21
|
+
"w": str(self._w), "h": str(self._h),
|
|
22
|
+
"name": self._name,
|
|
23
|
+
},
|
|
24
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ..shared.page_scope import PageScope
|
|
4
|
+
from .canvas_node import CanvasNode
|
|
5
|
+
from .clip import Clip
|
|
6
|
+
from .layer_options import LayerOptions
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LayerNode(CanvasNode):
|
|
10
|
+
"""A canvas layer containing canvas primitives."""
|
|
11
|
+
|
|
12
|
+
__slots__ = ("_nodes", "_options")
|
|
13
|
+
|
|
14
|
+
def __init__(self, nodes: list, options: LayerOptions | None = None):
|
|
15
|
+
self._nodes = nodes
|
|
16
|
+
self._options = options
|
|
17
|
+
|
|
18
|
+
def to_dict(self) -> dict:
|
|
19
|
+
attrs: dict = {}
|
|
20
|
+
o = self._options
|
|
21
|
+
if o is not None:
|
|
22
|
+
if o.page is not None:
|
|
23
|
+
attrs["page"] = o.page
|
|
24
|
+
if o.opacity is not None:
|
|
25
|
+
attrs["opacity"] = str(o.opacity)
|
|
26
|
+
if o.transform is not None:
|
|
27
|
+
attrs["transform"] = o.transform.matrix
|
|
28
|
+
if o.clip is not None:
|
|
29
|
+
c = o.clip
|
|
30
|
+
clip: dict = {"x": c.x, "y": c.y, "w": c.w, "h": c.h}
|
|
31
|
+
if c.border_radius != 0.0:
|
|
32
|
+
clip["borderRadius"] = c.border_radius
|
|
33
|
+
attrs["clip"] = clip
|
|
34
|
+
return {
|
|
35
|
+
"type": "canvas-layer",
|
|
36
|
+
"attrs": attrs,
|
|
37
|
+
"nodes": [n.to_dict() for n in self._nodes],
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from .transform import Transform
|
|
6
|
+
from .clip import Clip
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class LayerOptions:
|
|
11
|
+
page: str | None = None
|
|
12
|
+
opacity: float | None = None
|
|
13
|
+
transform: Transform | None = None
|
|
14
|
+
clip: Clip | None = None
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .canvas_node import CanvasNode
|
|
4
|
+
from .styles import LineStyle
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LineNode(CanvasNode):
|
|
8
|
+
__slots__ = ("_x1", "_y1", "_x2", "_y2", "_style")
|
|
9
|
+
|
|
10
|
+
def __init__(self, x1: float, y1: float, x2: float, y2: float, style: LineStyle | None = None):
|
|
11
|
+
self._x1 = x1
|
|
12
|
+
self._y1 = y1
|
|
13
|
+
self._x2 = x2
|
|
14
|
+
self._y2 = y2
|
|
15
|
+
self._style = style
|
|
16
|
+
|
|
17
|
+
def to_dict(self) -> dict:
|
|
18
|
+
attrs: dict = {
|
|
19
|
+
"x1": str(self._x1), "y1": str(self._y1),
|
|
20
|
+
"x2": str(self._x2), "y2": str(self._y2),
|
|
21
|
+
}
|
|
22
|
+
s = self._style
|
|
23
|
+
if s is not None:
|
|
24
|
+
if s.stroke is not None: attrs["stroke"] = s.stroke
|
|
25
|
+
if s.stroke_width is not None: attrs["stroke-width"] = str(s.stroke_width)
|
|
26
|
+
if s.stroke_dash is not None: attrs["stroke-dash"] = " ".join(str(v) for v in s.stroke_dash)
|
|
27
|
+
if s.line_cap is not None: attrs["line-cap"] = str(s.line_cap)
|
|
28
|
+
if s.line_join is not None: attrs["line-join"] = str(s.line_join)
|
|
29
|
+
return {"type": "canvas-line", "attrs": attrs}
|