diff --git a/.github/fabricbot.json b/.github/fabricbot.json
deleted file mode 100644
index a42cda55ad..0000000000
--- a/.github/fabricbot.json
+++ /dev/null
@@ -1,2834 +0,0 @@
-{
- "version": "1.0",
- "tasks": [
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssueCommentResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "operator": "not",
- "operands": [
- {
- "name": "isOpen",
- "parameters": {}
- }
- ]
- },
- {
- "name": "isAction",
- "parameters": {
- "action": "created"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "operator": "or",
- "operands": [
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ]
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 7
- }
- }
- ]
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isCloseAndComment",
- "parameters": {}
- }
- ]
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": {
- "type": "author"
- }
- }
- },
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "none"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issue_comment"
- ],
- "taskName": "[Idle Issue Management] For issues closed due to inactivity, re-open an issue if issue author posts a reply within 7 days.",
- "actions": [
- {
- "name": "reopenIssue",
- "parameters": {}
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- },
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/needs-attention"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssueCommentResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "action": "created"
- }
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isOpen",
- "parameters": {}
- }
- ]
- },
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "read"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 7
- }
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isCloseAndComment",
- "parameters": {}
- }
- ]
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issue_comment"
- ],
- "taskName": "[Closed Issue Management] For issues closed with no activity over 7 days, ask non-contributor to consider opening a new issue instead.",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!"
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "frequency": [
- {
- "weekDay": 0,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 1,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 2,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 3,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 4,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 5,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- },
- {
- "weekDay": 6,
- "hours": [
- 1,
- 4,
- 7,
- 10,
- 13,
- 16,
- 19,
- 22
- ],
- "timezoneOffset": -8
- }
- ],
- "searchTerms": [
- {
- "name": "isClosed",
- "parameters": {}
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 30
- }
- },
- {
- "name": "isUnlocked",
- "parameters": {}
- },
- {
- "name": "isIssue",
- "parameters": {}
- }
- ],
- "taskName": "[Closed Issue Management] Lock issues closed without activity for over 30 days",
- "actions": [
- {
- "name": "lockIssue",
- "parameters": {
- "reason": "resolved"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssueCommentResponder",
- "version": "1.0",
- "config": {
- "taskName": "[Idle Issue Management] Replace needs author feedback label with needs attention label when the author comments on an issue",
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "action": "created"
- }
- },
- {
- "operator": "or",
- "operands": [
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ]
- },
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "operator": "or",
- "operands": [
- {
- "operator": "and",
- "operands": [
- {
- "operator": "not",
- "operands": [
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "write"
- }
- }
- ]
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "admin"
- }
- }
- ]
- }
- ]
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": {
- "type": "author"
- }
- }
- }
- ]
- }
- ]
- },
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/needs-attention"
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ],
- "eventType": "issue",
- "eventNames": [
- "issue_comment"
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "taskName": "[Closed Issue Management] Remove no recent activity label from issues",
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "operator": "not",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "action": "closed"
- }
- }
- ]
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ]
- },
- "actions": [
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ],
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssueCommentResponder",
- "version": "1.0",
- "config": {
- "taskName": "[Idle Issue Management] Remove no recent activity label when an issue is commented on",
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ]
- },
- "actions": [
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ],
- "eventType": "issue",
- "eventNames": [
- "issue_comment"
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "taskName": "[Idle Issue Management] Close stale `status/needs-info` issues",
- "frequency": [
- {
- "weekDay": 1,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 2,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 3,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 4,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 5,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- }
- ],
- "searchTerms": [
- {
- "name": "isIssue",
- "parameters": {}
- },
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 3
- }
- }
- ],
- "actions": [
- {
- "name": "closeIssue",
- "parameters": {}
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "taskName": "[Idle Issue Management] Close stale `status/needs-repro` issues",
- "frequency": [
- {
- "weekDay": 1,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 2,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 3,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 4,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 5,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- }
- ],
- "searchTerms": [
- {
- "name": "isIssue",
- "parameters": {}
- },
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 3
- }
- }
- ],
- "actions": [
- {
- "name": "closeIssue",
- "parameters": {}
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "taskName": "[Idle Issue Management] Add no recent activity label to `status/needs-info` issues",
- "frequency": [
- {
- "weekDay": 1,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 2,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 3,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 4,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 5,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- }
- ],
- "searchTerms": [
- {
- "name": "isIssue",
- "parameters": {}
- },
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 4
- }
- },
- {
- "name": "noLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ],
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "name": "addReply",
- "parameters": {
- "comment": "This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. If it *is* closed, feel free to comment when you are able to provide the additional information and we will re-investigate."
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "taskName": "[Idle Issue Management] Add no recent activity label to `status/needs-repro` issues",
- "frequency": [
- {
- "weekDay": 1,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 2,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 3,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 4,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- },
- {
- "weekDay": 5,
- "hours": [
- 0,
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10,
- 11,
- 12,
- 13,
- 14,
- 15,
- 16,
- 17,
- 18,
- 19,
- 20,
- 21,
- 22,
- 23
- ]
- }
- ],
- "searchTerms": [
- {
- "name": "isIssue",
- "parameters": {}
- },
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 4
- }
- },
- {
- "name": "noLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- }
- ],
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/no-recent-activity"
- }
- },
- {
- "name": "addReply",
- "parameters": {
- "comment": "This issue has been automatically marked as stale because it has been marked as requiring author feedback to reproduce the issue but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. If it *is* closed, feel free to comment when you are able to provide the additional information and we will re-investigate."
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "action": "opened"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "dotnet-maestro[bot]",
- "association": "CONTRIBUTOR"
- }
- },
- {
- "name": "titleContains",
- "parameters": {
- "titlePattern": "Update dependencies"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "[Infrastructure PRs] Add area-infrastructure label to dependency update Pull Requests",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "area/infrastructure 🏗️"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "addedToMilestone",
- "parameters": {
- "milestoneName": "Backlog"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Comment: Issue moved to Backlog",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time."
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/needs-info"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Replace `status/needs-info` with `status/pr-needs-author-input` for PRs",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hello. I see that you've just added `status/needs-info` label to this PR.\nThat label is for Issues and not for PRs. Don't worry, I'm going to replace it with the correct one."
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-info"
- }
- },
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Remove `status/needs-repro` from PRs",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hello. I see that you've just added `status/needs-repro` label to this PR.\nThat label is for Issues and not for PRs, so I removed it."
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/needs-info"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add comment when `status/needs-info` is applied to issue",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hi @${issueAuthor}. We have added the `status/needs-info` label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time."
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/needs-repro"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add comment when `status/needs-repro` is applied to issue",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hi @${issueAuthor}. We have added the `status/needs-repro` label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone.\n\nThis issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time."
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "or",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-newcontrol"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-general"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-webview"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-datetimepicker"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-picker"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-switch"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-dualscreen"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-checkbox"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-border"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-label"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-button"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-dialogalert"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-entry"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-frame"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-stepper"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-refreshview"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-image"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-activityindicator"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-radiobutton"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-slider"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-progressbar"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-pages"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-map"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add area/controls label when any 'control-X' label is applied to the issue",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "area/controls 🎮"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "or",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-newcontrol"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-general"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-webview"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-datetimepicker"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-picker"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-switch"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-dualscreen"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-checkbox"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-border"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-label"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-button"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-dialogalert"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-entry"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-frame"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-stepper"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-refreshview"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-image"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-activityindicator"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-radiobutton"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-slider"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-progressbar"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-pages"
- }
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "control-map"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Add area/controls label when any 'control-X' label is applied to the PR",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "area/controls 🎮"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "action": "opened"
- }
- },
- {
- "operator": "or",
- "operands": [
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "alexeystrakh"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "alexkblount"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "BenBtg"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "DeanFaizal"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "jgold6"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "jmongaras"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "jonlipsky"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "JoonghyunCho"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "juanlao"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "migueBarrera"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "mikeparker104"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "myroot"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "rookiejava"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "shyunMin"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "sung-su"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "Sweekriti91"
- }
- }
- ]
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add 'partner' label when issue is opened by a partner",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "partner"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/move-to-vs-feedback"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Ask user to use VS Feedback for VS issues",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Thanks for the issue report @${issueAuthor}! This issue appears to be a problem with Visual Studio, so we ask that you use the VS feedback tool to report the issue. That way it will get to the routed to the team that owns this experience in VS.\n\nIf you encounter a problem with Visual Studio, we want to know about it so that we can diagnose and fix it. By using the Report a Problem tool, you can collect detailed information about the problem, and send it to Microsoft with just a few button clicks.\n\n1. Go to the [VS feedback tool](https://docs.microsoft.com/visualstudio/ide/how-to-report-a-problem-with-visual-studio?view=vs-2022) to report the issue\n2. Close this bug, and consider adding a link to the VS Feedback issue so that others can follow its activity there.\n\nThis issue will be automatically closed in 3 days if there are no further comments."
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "frequency": [
- {
- "weekDay": 0,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 1,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 2,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 3,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 4,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 5,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- },
- {
- "weekDay": 6,
- "hours": [
- 0,
- 6,
- 12,
- 18
- ]
- }
- ],
- "searchTerms": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/move-to-vs-feedback"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 3
- }
- }
- ],
- "taskName": "Close `status/move-to-vs-feedback` after 3 days of no activity",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "This issue is being closed due to inactivity. If this issue is still affecting you, please follow the steps above to use the VS Feedback Tool to report the issue."
- }
- },
- {
- "name": "closeIssue",
- "parameters": {}
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssueCommentResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "isAction",
- "parameters": {
- "action": "created"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/move-to-vs-feedback"
- }
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 3
- }
- }
- ]
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isCloseAndComment",
- "parameters": {}
- }
- ]
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": {
- "type": "author"
- }
- }
- },
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "none"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issue_comment"
- ],
- "taskName": "For issues labeled with `status/move-to-vs-feedback` mark as `status/needs-attention` if there is activity",
- "actions": [
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/move-to-vs-feedback"
- }
- },
- {
- "name": "addLabel",
- "parameters": {
- "label": "status/needs-attention"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "isAction",
- "parameters": {
- "user": "roubachof",
- "action": "opened"
- }
- },
- {
- "operator": "or",
- "operands": [
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "roubachof"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "davidbritch"
- }
- }
- ]
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add 'i/great-reporter' when issue is opened by an author we know opens high quality issues",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "i/great-reporter"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "IssuesOnlyResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/try-latest-version"
- }
- }
- ]
- },
- "eventType": "issue",
- "eventNames": [
- "issues",
- "project_card"
- ],
- "taskName": "Add comment when `status/try-latest-version` is applied to the issue",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hi @${issueAuthor}. We have added the `status/try-latest-version` label to this issue, which indicates that we'd like you to try and reproduce this issue on the latest available public version. This can happen because we think that this issue was fixed in a version that has just been released, or the information provided by you indicates that you might be working with an older version.\n\nIf the issue still persists, please let us know with any additional details and ideally a reproduction project provided through a GitHub repository.\n\nThis issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time."
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "frequency": [
- {
- "weekDay": 0,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 1,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 2,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 3,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 4,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 5,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 6,
- "hours": [
- 3,
- 15
- ],
- "timezoneOffset": 2
- }
- ],
- "searchTerms": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/try-latest-version"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 7
- }
- }
- ],
- "taskName": "[Idle Issue Management] Close stale `status/try-latest-version` issues",
- "actions": [
- {
- "name": "closeIssue",
- "parameters": {}
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "read"
- }
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "dotnet-maestro"
- }
- }
- ]
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "isActivitySender",
- "parameters": {
- "user": "dotnet-maestro-bot"
- }
- }
- ]
- },
- {
- "name": "isAction",
- "parameters": {
- "action": "opened"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Add 'community ✨' label to community contributions",
- "actions": [
- {
- "name": "addLabel",
- "parameters": {
- "label": "community ✨"
- }
- },
- {
- "name": "addReactionToIssue",
- "parameters": {
- "reaction": "heart"
- }
- },
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hey there @${issueAuthor}! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed."
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "frequency": [
- {
- "weekDay": 0,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 1,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 2,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 3,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 4,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 5,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 6,
- "hours": [
- 2,
- 5,
- 8,
- 11,
- 14,
- 17,
- 20,
- 23
- ],
- "timezoneOffset": 2
- }
- ],
- "searchTerms": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "isPr",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 10
- }
- },
- {
- "name": "noLabel",
- "parameters": {
- "label": "stale"
- }
- }
- ],
- "taskName": "Stale PR reminder",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hi @${issueAuthor}.\nIt seems you haven't touched this PR for the last two weeks. To avoid accumulating old PRs, we're marking it as `stale`. As a result, it will be closed if no further activity occurs **within 4 days of this comment**."
- }
- },
- {
- "name": "addLabel",
- "parameters": {
- "label": "stale"
- }
- }
- ]
- }
- },
- {
- "taskType": "scheduled",
- "capabilityId": "ScheduledSearch",
- "subCapability": "ScheduledSearch",
- "version": "1.1",
- "config": {
- "frequency": [
- {
- "weekDay": 0,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 1,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 2,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 3,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 4,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 5,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- },
- {
- "weekDay": 6,
- "hours": [
- 3,
- 7,
- 11,
- 15,
- 19,
- 23
- ],
- "timezoneOffset": 2
- }
- ],
- "searchTerms": [
- {
- "name": "isOpen",
- "parameters": {}
- },
- {
- "name": "isPr",
- "parameters": {}
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "stale"
- }
- },
- {
- "name": "noActivitySince",
- "parameters": {
- "days": 4
- }
- }
- ],
- "taskName": "Close stale PRs",
- "actions": [
- {
- "name": "closeIssue",
- "parameters": {}
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "hasLabel",
- "parameters": {
- "label": "stale"
- }
- },
- {
- "name": "hasLabel",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- },
- {
- "name": "isActivitySender",
- "parameters": {
- "user": {
- "type": "author"
- }
- }
- },
- {
- "operator": "not",
- "operands": [
- {
- "name": "activitySenderHasPermissions",
- "parameters": {
- "permissions": "write"
- }
- }
- ]
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Revitalize stale PR and reopen",
- "actions": [
- {
- "name": "reopenIssue",
- "parameters": {}
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "stale"
- }
- },
- {
- "name": "removeLabel",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- }
- ]
- }
- },
- {
- "taskType": "trigger",
- "capabilityId": "IssueResponder",
- "subCapability": "PullRequestResponder",
- "version": "1.0",
- "config": {
- "conditions": {
- "operator": "and",
- "operands": [
- {
- "name": "labelAdded",
- "parameters": {
- "label": "status/pr-needs-author-input"
- }
- }
- ]
- },
- "eventType": "pull_request",
- "eventNames": [
- "pull_request",
- "issues",
- "project_card"
- ],
- "taskName": "Add comment when `status/pr-needs-author-input` is applied to PR",
- "actions": [
- {
- "name": "addReply",
- "parameters": {
- "comment": "Hi @${issueAuthor}. We have added the `status/pr-needs-author-input` label to this issue, which indicates that we have an open question/action for you before we can take further action. This PRwill be closed automatically in 14 days if we do not hear back from you by then - please feel free to re-open it if you come back to this PR after that time."
- }
- }
- ]
- }
- }
- ],
- "userGroups": []
-}
\ No newline at end of file
diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml
new file mode 100644
index 0000000000..5dc7e5b351
--- /dev/null
+++ b/.github/policies/resourceManagement.yml
@@ -0,0 +1,562 @@
+id:
+name: GitOps.PullRequestIssueManagement
+description: GitOps.PullRequestIssueManagement primitive
+owner:
+resource: repository
+disabled: false
+where:
+configuration:
+ resourceManagementConfiguration:
+ scheduledSearches:
+ - description: '[Idle Issue Management] Close stale `status/needs-info` issues'
+ frequencies:
+ - weekday:
+ day: Monday
+ time: 0:0
+ - weekday:
+ day: Tuesday
+ time: 0:0
+ - weekday:
+ day: Wednesday
+ time: 0:0
+ - weekday:
+ day: Thursday
+ time: 0:0
+ - weekday:
+ day: Friday
+ time: 0:0
+ filters:
+ - isIssue
+ - isOpen
+ - hasLabel:
+ label: status/needs-info
+ - hasLabel:
+ label: status/no-recent-activity
+ - noActivitySince:
+ days: 3
+ actions:
+ - closeIssue
+ - description: '[Idle Issue Management] Close stale `status/needs-repro` issues'
+ frequencies:
+ - weekday:
+ day: Monday
+ time: 0:0
+ - weekday:
+ day: Tuesday
+ time: 0:0
+ - weekday:
+ day: Wednesday
+ time: 0:0
+ - weekday:
+ day: Thursday
+ time: 0:0
+ - weekday:
+ day: Friday
+ time: 0:0
+ filters:
+ - isIssue
+ - isOpen
+ - hasLabel:
+ label: status/needs-repro
+ - hasLabel:
+ label: status/no-recent-activity
+ - noActivitySince:
+ days: 3
+ actions:
+ - closeIssue
+ - description: '[Idle Issue Management] Add no recent activity label to `status/needs-info` issues'
+ frequencies:
+ - weekday:
+ day: Monday
+ time: 0:0
+ - weekday:
+ day: Tuesday
+ time: 0:0
+ - weekday:
+ day: Wednesday
+ time: 0:0
+ - weekday:
+ day: Thursday
+ time: 0:0
+ - weekday:
+ day: Friday
+ time: 0:0
+ filters:
+ - isIssue
+ - isOpen
+ - hasLabel:
+ label: status/needs-info
+ - noActivitySince:
+ days: 4
+ - isNotLabeledWith:
+ label: status/no-recent-activity
+ actions:
+ - addLabel:
+ label: status/no-recent-activity
+ - addReply:
+ reply: This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. If it *is* closed, feel free to comment when you are able to provide the additional information and we will re-investigate.
+ - description: '[Idle Issue Management] Add no recent activity label to `status/needs-repro` issues'
+ frequencies:
+ - weekday:
+ day: Monday
+ time: 0:0
+ - weekday:
+ day: Tuesday
+ time: 0:0
+ - weekday:
+ day: Wednesday
+ time: 0:0
+ - weekday:
+ day: Thursday
+ time: 0:0
+ - weekday:
+ day: Friday
+ time: 0:0
+ filters:
+ - isIssue
+ - isOpen
+ - hasLabel:
+ label: status/needs-repro
+ - noActivitySince:
+ days: 4
+ - isNotLabeledWith:
+ label: status/no-recent-activity
+ actions:
+ - addLabel:
+ label: status/no-recent-activity
+ - addReply:
+ reply: This issue has been automatically marked as stale because it has been marked as requiring author feedback to reproduce the issue but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. If it *is* closed, feel free to comment when you are able to provide the additional information and we will re-investigate.
+ - description: Close `status/move-to-vs-feedback` after 3 days of no activity
+ frequencies:
+ - hourly:
+ hour: 6
+ filters:
+ - isOpen
+ - hasLabel:
+ label: status/move-to-vs-feedback
+ - noActivitySince:
+ days: 3
+ actions:
+ - addReply:
+ reply: This issue is being closed due to inactivity. If this issue is still affecting you, please follow the steps above to use the VS Feedback Tool to report the issue.
+ - closeIssue
+ - description: '[Idle Issue Management] Close stale `status/try-latest-version` issues'
+ frequencies:
+ - hourly:
+ hour: 12
+ filters:
+ - isOpen
+ - hasLabel:
+ label: status/try-latest-version
+ - noActivitySince:
+ days: 7
+ actions:
+ - closeIssue
+ - description: Stale PR reminder
+ frequencies:
+ - hourly:
+ hour: 3
+ filters:
+ - isOpen
+ - isPullRequest
+ - hasLabel:
+ label: status/pr-needs-author-input
+ - noActivitySince:
+ days: 10
+ - isNotLabeledWith:
+ label: stale
+ actions:
+ - addReply:
+ reply: >-
+ Hi @${issueAuthor}.
+
+ It seems you haven't touched this PR for the last two weeks. To avoid accumulating old PRs, we're marking it as `stale`. As a result, it will be closed if no further activity occurs **within 4 days of this comment**.
+ - addLabel:
+ label: stale
+ - description: Close stale PRs
+ frequencies:
+ - hourly:
+ hour: 4
+ filters:
+ - isOpen
+ - isPullRequest
+ - hasLabel:
+ label: status/pr-needs-author-input
+ - hasLabel:
+ label: stale
+ - noActivitySince:
+ days: 4
+ actions:
+ - closeIssue
+ eventResponderTasks:
+ - if:
+ - payloadType: Issue_Comment
+ - isAction:
+ action: Created
+ - or:
+ - hasLabel:
+ label: status/needs-info
+ - hasLabel:
+ label: status/needs-repro
+ - isOpen
+ - or:
+ - and:
+ - not:
+ activitySenderHasPermission:
+ permission: Write
+ - not:
+ activitySenderHasPermission:
+ permission: Admin
+ - isActivitySender:
+ issueAuthor: True
+ then:
+ - addLabel:
+ label: status/needs-attention
+ - removeLabel:
+ label: status/needs-info
+ - removeLabel:
+ label: status/needs-repro
+ description: '[Idle Issue Management] Replace needs author feedback label with needs attention label when the author comments on an issue'
+ - if:
+ - payloadType: Issues
+ - not:
+ isAction:
+ action: Closed
+ - hasLabel:
+ label: status/no-recent-activity
+ then:
+ - removeLabel:
+ label: status/no-recent-activity
+ description: '[Closed Issue Management] Remove no recent activity label from issues'
+ - if:
+ - payloadType: Issue_Comment
+ - hasLabel:
+ label: status/no-recent-activity
+ then:
+ - removeLabel:
+ label: status/no-recent-activity
+ description: '[Idle Issue Management] Remove no recent activity label when an issue is commented on'
+ - if:
+ - payloadType: Pull_Request
+ - isAction:
+ action: Opened
+ - isActivitySender:
+ user: dotnet-maestro[bot]
+ issueAuthor: False
+ - titleContains:
+ pattern: Update dependencies
+ isRegex: False
+ then:
+ - addLabel:
+ label: "area/infrastructure \U0001F3D7️"
+ description: '[Infrastructure PRs] Add area-infrastructure label to dependency update Pull Requests'
+ - if:
+ - payloadType: Pull_Request
+ - labelAdded:
+ label: status/needs-info
+ then:
+ - addReply:
+ reply: >-
+ Hello. I see that you've just added `status/needs-info` label to this PR.
+
+ That label is for Issues and not for PRs. Don't worry, I'm going to replace it with the correct one.
+ - removeLabel:
+ label: status/needs-info
+ - addLabel:
+ label: status/pr-needs-author-input
+ description: Replace `status/needs-info` with `status/pr-needs-author-input` for PRs
+ - if:
+ - payloadType: Pull_Request
+ - labelAdded:
+ label: status/needs-repro
+ then:
+ - addReply:
+ reply: >-
+ Hello. I see that you've just added `status/needs-repro` label to this PR.
+
+ That label is for Issues and not for PRs, so I removed it.
+ - removeLabel:
+ label: status/needs-repro
+ description: Remove `status/needs-repro` from PRs
+ - if:
+ - payloadType: Issues
+ - labelAdded:
+ label: status/needs-info
+ then:
+ - addReply:
+ reply: Hi @${issueAuthor}. We have added the `status/needs-info` label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
+ description: Add comment when `status/needs-info` is applied to issue
+ - if:
+ - payloadType: Issues
+ - labelAdded:
+ label: status/needs-repro
+ then:
+ - addReply:
+ reply: >-
+ Hi @${issueAuthor}. We have added the `status/needs-repro` label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone.
+
+
+ This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
+ description: Add comment when `status/needs-repro` is applied to issue
+ - if:
+ - payloadType: Issues
+ - or:
+ - labelAdded:
+ label: control-newcontrol
+ - labelAdded:
+ label: control-general
+ - labelAdded:
+ label: control-webview
+ - labelAdded:
+ label: control-datetimepicker
+ - labelAdded:
+ label: control-picker
+ - labelAdded:
+ label: control-switch
+ - labelAdded:
+ label: control-dualscreen
+ - labelAdded:
+ label: control-checkbox
+ - labelAdded:
+ label: control-border
+ - labelAdded:
+ label: control-label
+ - labelAdded:
+ label: control-button
+ - labelAdded:
+ label: control-dialogalert
+ - labelAdded:
+ label: control-entry
+ - labelAdded:
+ label: control-frame
+ - labelAdded:
+ label: control-stepper
+ - labelAdded:
+ label: control-refreshview
+ - labelAdded:
+ label: control-image
+ - labelAdded:
+ label: control-activityindicator
+ - labelAdded:
+ label: control-radiobutton
+ - labelAdded:
+ label: control-slider
+ - labelAdded:
+ label: control-progressbar
+ - labelAdded:
+ label: control-pages
+ - labelAdded:
+ label: control-map
+ then:
+ - addLabel:
+ label: "area/controls \U0001F3AE"
+ description: Add area/controls label when any 'control-X' label is applied to the issue
+ - if:
+ - payloadType: Pull_Request
+ - or:
+ - labelAdded:
+ label: control-newcontrol
+ - labelAdded:
+ label: control-general
+ - labelAdded:
+ label: control-webview
+ - labelAdded:
+ label: control-datetimepicker
+ - labelAdded:
+ label: control-picker
+ - labelAdded:
+ label: control-switch
+ - labelAdded:
+ label: control-dualscreen
+ - labelAdded:
+ label: control-checkbox
+ - labelAdded:
+ label: control-border
+ - labelAdded:
+ label: control-label
+ - labelAdded:
+ label: control-button
+ - labelAdded:
+ label: control-dialogalert
+ - labelAdded:
+ label: control-entry
+ - labelAdded:
+ label: control-frame
+ - labelAdded:
+ label: control-stepper
+ - labelAdded:
+ label: control-refreshview
+ - labelAdded:
+ label: control-image
+ - labelAdded:
+ label: control-activityindicator
+ - labelAdded:
+ label: control-radiobutton
+ - labelAdded:
+ label: control-slider
+ - labelAdded:
+ label: control-progressbar
+ - labelAdded:
+ label: control-pages
+ - labelAdded:
+ label: control-map
+ then:
+ - addLabel:
+ label: "area/controls \U0001F3AE"
+ description: Add area/controls label when any 'control-X' label is applied to the PR
+ - if:
+ - payloadType: Issues
+ - isAction:
+ action: Opened
+ - or:
+ - isActivitySender:
+ user: alexeystrakh
+ issueAuthor: False
+ - isActivitySender:
+ user: alexkblount
+ issueAuthor: False
+ - isActivitySender:
+ user: BenBtg
+ issueAuthor: False
+ - isActivitySender:
+ user: DeanFaizal
+ issueAuthor: False
+ - isActivitySender:
+ user: jgold6
+ issueAuthor: False
+ - isActivitySender:
+ user: jmongaras
+ issueAuthor: False
+ - isActivitySender:
+ user: jonlipsky
+ issueAuthor: False
+ - isActivitySender:
+ user: JoonghyunCho
+ issueAuthor: False
+ - isActivitySender:
+ user: juanlao
+ issueAuthor: False
+ - isActivitySender:
+ user: migueBarrera
+ issueAuthor: False
+ - isActivitySender:
+ user: mikeparker104
+ issueAuthor: False
+ - isActivitySender:
+ user: myroot
+ issueAuthor: False
+ - isActivitySender:
+ user: rookiejava
+ issueAuthor: False
+ - isActivitySender:
+ user: shyunMin
+ issueAuthor: False
+ - isActivitySender:
+ user: sung-su
+ issueAuthor: False
+ - isActivitySender:
+ user: Sweekriti91
+ issueAuthor: False
+ then:
+ - addLabel:
+ label: partner
+ description: Add 'partner' label when issue is opened by a partner
+ - if:
+ - payloadType: Issues
+ - isOpen
+ - labelAdded:
+ label: status/move-to-vs-feedback
+ then:
+ - addReply:
+ reply: >-
+ Thanks for the issue report @${issueAuthor}! This issue appears to be a problem with Visual Studio, so we ask that you use the VS feedback tool to report the issue. That way it will get to the routed to the team that owns this experience in VS.
+
+
+ If you encounter a problem with Visual Studio, we want to know about it so that we can diagnose and fix it. By using the Report a Problem tool, you can collect detailed information about the problem, and send it to Microsoft with just a few button clicks.
+
+
+ 1. Go to the [VS feedback tool](https://docs.microsoft.com/visualstudio/ide/how-to-report-a-problem-with-visual-studio?view=vs-2022) to report the issue
+
+ 2. Close this bug, and consider adding a link to the VS Feedback issue so that others can follow its activity there.
+
+
+ This issue will be automatically closed in 3 days if there are no further comments.
+ description: Ask user to use VS Feedback for VS issues
+ - if:
+ - payloadType: Issues
+ - isAction:
+ action: Opened
+ - or:
+ - isActivitySender:
+ user: roubachof
+ issueAuthor: False
+ - isActivitySender:
+ user: davidbritch
+ issueAuthor: False
+ then:
+ - addLabel:
+ label: i/great-reporter
+ description: Add 'i/great-reporter' when issue is opened by an author we know opens high quality issues
+ - if:
+ - payloadType: Issues
+ - labelAdded:
+ label: status/try-latest-version
+ then:
+ - addReply:
+ reply: >-
+ Hi @${issueAuthor}. We have added the `status/try-latest-version` label to this issue, which indicates that we'd like you to try and reproduce this issue on the latest available public version. This can happen because we think that this issue was fixed in a version that has just been released, or the information provided by you indicates that you might be working with an older version.
+
+
+ If the issue still persists, please let us know with any additional details and ideally a reproduction project provided through a GitHub repository.
+
+
+ This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
+ description: Add comment when `status/try-latest-version` is applied to the issue
+ - if:
+ - payloadType: Pull_Request
+ - activitySenderHasPermission:
+ permission: Read
+ - not:
+ isActivitySender:
+ user: dotnet-maestro
+ issueAuthor: False
+ - not:
+ isActivitySender:
+ user: dotnet-maestro-bot
+ issueAuthor: False
+ - isAction:
+ action: Opened
+ then:
+ - addLabel:
+ label: community ✨
+ - addReply:
+ reply: Hey there @${issueAuthor}! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.
+ description: Add 'community ✨' label to community contributions
+ - if:
+ - payloadType: Pull_Request
+ - hasLabel:
+ label: stale
+ - hasLabel:
+ label: status/pr-needs-author-input
+ - isActivitySender:
+ issueAuthor: True
+ - not:
+ activitySenderHasPermission:
+ permission: Write
+ then:
+ - reopenIssue
+ - removeLabel:
+ label: stale
+ - removeLabel:
+ label: status/pr-needs-author-input
+ description: Revitalize stale PR and reopen
+ - if:
+ - payloadType: Pull_Request
+ - labelAdded:
+ label: status/pr-needs-author-input
+ then:
+ - addReply:
+ reply: Hi @${issueAuthor}. We have added the `status/pr-needs-author-input` label to this issue, which indicates that we have an open question/action for you before we can take further action. This PRwill be closed automatically in 14 days if we do not hear back from you by then - please feel free to re-open it if you come back to this PR after that time.
+ description: Add comment when `status/pr-needs-author-input` is applied to PR
+onFailure:
+onSuccess:
diff --git a/.github/workflows/similarissues.yml b/.github/workflows/similarissues.yml
new file mode 100644
index 0000000000..73a49f265b
--- /dev/null
+++ b/.github/workflows/similarissues.yml
@@ -0,0 +1,38 @@
+name: Find Similar Issues
+
+on:
+ issues:
+ types: [opened]
+ issue_comment:
+ types: [created]
+
+jobs:
+ getSimilarIssues:
+ runs-on: ubuntu-latest
+ if: >-
+ (github.event_name == 'issues' && github.event.action == 'opened') ||
+ (github.event_name == 'issue_comment' && github.event.action == 'created' && startsWith(github.event.comment.body, '/similarissues'))
+ outputs:
+ message: ${{ steps.getBody.outputs.message }}
+ steps:
+ - id: getBody
+ uses: craigloewen-msft/GitGudSimilarIssues@main
+ with:
+ issueTitle: ${{ github.event.issue.title }}
+ issueBody: ${{ github.event.issue.body }}
+ repo: ${{ github.repository }}
+ similaritytolerance: "0.70"
+ add-comment:
+ needs: getSimilarIssues
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+ if: needs.getSimilarIssues.outputs.message != ''
+ steps:
+ - name: Add comment
+ run: gh issue comment "$NUMBER" --repo "$REPO" --body "$BODY"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ NUMBER: ${{ github.event.issue.number }}
+ REPO: ${{ github.repository }}
+ BODY: ${{ needs.getSimilarIssues.outputs.message }}
diff --git a/README.md b/README.md
index 81a4dc0f4f..e20162e2ec 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,6 @@ However, these are easy to install as they are found on the various websites. If
Here are some links to show the differences in our code as compared to Google's code.
-What version are we on? [**m115**](https://github.com/google/skia/tree/chrome/m115)
-Are we up-to-date with Google? [Compare](https://github.com/mono/skia/compare/skiasharp...google:chrome/m115)
-What have we added? [Compare](https://github.com/google/skia/compare/chrome/m115...mono:skiasharp)
+What version are we on? [**m116**](https://github.com/google/skia/tree/chrome/m116)
+Are we up-to-date with Google? [Compare](https://github.com/mono/skia/compare/skiasharp...google:chrome/m116)
+What have we added? [Compare](https://github.com/google/skia/compare/chrome/m116...mono:skiasharp)
diff --git a/benchmarks/SkiaSharp.Benchmarks.sln b/benchmarks/SkiaSharp.Benchmarks.sln
index aea131389d..2cbfe66ee3 100644
--- a/benchmarks/SkiaSharp.Benchmarks.sln
+++ b/benchmarks/SkiaSharp.Benchmarks.sln
@@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Benchmarks", "Ski
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.SceneGraph", "..\binding\SkiaSharp.SceneGraph\SkiaSharp.SceneGraph.csproj", "{42B5D998-A676-4B50-B558-1D3ACA7D3FC4}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Resources", "..\binding\SkiaSharp.Resources\SkiaSharp.Resources.csproj", "{AD2C6978-4F5E-E592-B565-26C357877B2C}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Skottie", "..\binding\SkiaSharp.Skottie\SkiaSharp.Skottie.csproj", "{DD03EAA1-A85D-4588-8B84-8285EC1979C8}"
EndProject
Global
@@ -41,6 +43,10 @@ Global
{42B5D998-A676-4B50-B558-1D3ACA7D3FC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42B5D998-A676-4B50-B558-1D3ACA7D3FC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42B5D998-A676-4B50-B558-1D3ACA7D3FC4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD2C6978-4F5E-E592-B565-26C357877B2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD2C6978-4F5E-E592-B565-26C357877B2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD2C6978-4F5E-E592-B565-26C357877B2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD2C6978-4F5E-E592-B565-26C357877B2C}.Release|Any CPU.Build.0 = Release|Any CPU
{DD03EAA1-A85D-4588-8B84-8285EC1979C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD03EAA1-A85D-4588-8B84-8285EC1979C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD03EAA1-A85D-4588-8B84-8285EC1979C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/binding/Binding.Shared/PlatformConfiguration.cs b/binding/Binding.Shared/PlatformConfiguration.cs
index e3c3b8b481..7a1fbdf18f 100644
--- a/binding/Binding.Shared/PlatformConfiguration.cs
+++ b/binding/Binding.Shared/PlatformConfiguration.cs
@@ -18,42 +18,52 @@ public static class PlatformConfiguration
{
private const string LibCLibrary = "libc";
- public static bool IsUnix { get; }
+ public static bool IsUnix => IsMac || IsLinux;
- public static bool IsWindows { get; }
-
- public static bool IsMac { get; }
-
- public static bool IsLinux { get; }
-
- public static bool IsArm { get; }
-
- public static bool Is64Bit { get; }
+ public static bool IsWindows {
+#if WINDOWS_UWP
+ get => true;
+#elif NET6_0_OR_GREATER
+ get => OperatingSystem.IsWindows ();
+#else
+ get => RuntimeInformation.IsOSPlatform (OSPlatform.Windows);
+#endif
+ }
- static PlatformConfiguration ()
- {
+ public static bool IsMac {
#if WINDOWS_UWP
- IsMac = false;
- IsLinux = false;
- IsUnix = false;
- IsWindows = true;
-
- var arch = Package.Current.Id.Architecture;
- const ProcessorArchitecture arm64 = (ProcessorArchitecture)12;
- IsArm = arch == ProcessorArchitecture.Arm || arch == arm64;
+ get => false;
+#elif NET6_0_OR_GREATER
+ get => OperatingSystem.IsMacOS ();
#else
- IsMac = RuntimeInformation.IsOSPlatform (OSPlatform.OSX);
- IsLinux = RuntimeInformation.IsOSPlatform (OSPlatform.Linux);
- IsUnix = IsMac || IsLinux;
- IsWindows = RuntimeInformation.IsOSPlatform (OSPlatform.Windows);
+ get => RuntimeInformation.IsOSPlatform (OSPlatform.OSX);
+#endif
+ }
- var arch = RuntimeInformation.ProcessArchitecture;
- IsArm = arch == Architecture.Arm || arch == Architecture.Arm64;
+ public static bool IsLinux {
+#if WINDOWS_UWP
+ get => false;
+#elif NET6_0_OR_GREATER
+ get => OperatingSystem.IsLinux ();
+#else
+ get => RuntimeInformation.IsOSPlatform (OSPlatform.Linux);
#endif
+ }
- Is64Bit = IntPtr.Size == 8;
+ public static bool IsArm {
+#if WINDOWS_UWP
+ get {
+ var arch = Package.Current.Id.Architecture;
+ const ProcessorArchitecture arm64 = (ProcessorArchitecture)12;
+ return arch == ProcessorArchitecture.Arm || arch == arm64;
+ }
+#else
+ get => RuntimeInformation.ProcessArchitecture is Architecture.Arm or Architecture.Arm64;
+#endif
}
+ public static bool Is64Bit => IntPtr.Size == 8;
+
private static string linuxFlavor;
public static string LinuxFlavor
diff --git a/binding/Directory.Build.targets b/binding/Directory.Build.targets
index f6e780a0ff..813aac0552 100644
--- a/binding/Directory.Build.targets
+++ b/binding/Directory.Build.targets
@@ -4,6 +4,10 @@
+
+
+
+
SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library.
It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
diff --git a/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets b/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets
new file mode 100644
index 0000000000..89e4c652b7
--- /dev/null
+++ b/binding/IncludeNativeAssets.SkiaSharp.WinUI.targets
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binding/NativeAssets.Build.targets b/binding/NativeAssets.Build.targets
index cd68c556fa..d34c35f239 100644
--- a/binding/NativeAssets.Build.targets
+++ b/binding/NativeAssets.Build.targets
@@ -33,16 +33,20 @@
-
+ <_NativeWindowsPackageFileToUse Include="@(NativeWindowsPackageFile->HasMetadata('Folder'))" />
+ <_NativeWindowsPackageFileWithNoFolder Include="@(NativeWindowsPackageFile)" />
+ <_NativeWindowsPackageFileWithNoFolder Remove="@(_NativeWindowsPackageFileToUse)" />
+ <_NativeWindowsPackageFileToUse Include="@(_NativeWindowsPackageFileWithNoFolder)" Folder="native" />
+
<_CompletedNativeWindowsPackageFile
- Include="@(NativeWindowsPackageFile)"
+ Include="@(_NativeWindowsPackageFileToUse)"
TargetFramework="%(RuntimeIdentifier)"
- TargetPath="native\%(Filename)%(Extension)"
- PackagePath="runtimes\%(RuntimeIdentifier)\native\%(Filename)%(Extension)" />
+ TargetPath="%(Folder)\%(Filename)%(Extension)"
+ PackagePath="runtimes\%(RuntimeIdentifier)\%(Folder)\%(Filename)%(Extension)" />
<_BuildOutputInPackage Remove="@(_BuildOutputInPackage)" />
<_BuildOutputInPackage Include="@(_CompletedNativeWindowsPackageFile)" Condition="'%(Extension)' != '.pdb'" />
<_TargetPathsToSymbols Remove="@(_TargetPathsToSymbols)" />
diff --git a/binding/SkiaSharp.NativeAssets.WinUI/SkiaSharp.NativeAssets.WinUI.csproj b/binding/SkiaSharp.NativeAssets.WinUI/SkiaSharp.NativeAssets.WinUI.csproj
new file mode 100644
index 0000000000..fab3a0d1e0
--- /dev/null
+++ b/binding/SkiaSharp.NativeAssets.WinUI/SkiaSharp.NativeAssets.WinUI.csproj
@@ -0,0 +1,16 @@
+
+
+ $(WindowsTargetFrameworks)
+ SkiaSharp
+ $(PackagingGroup) - Native Assets for Windows UI (WinUI 3)
+ true
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/binding/SkiaSharp.Resources/Properties/SkiaSharpResourcesAssemblyInfo.cs b/binding/SkiaSharp.Resources/Properties/SkiaSharpResourcesAssemblyInfo.cs
new file mode 100644
index 0000000000..32dd31681e
--- /dev/null
+++ b/binding/SkiaSharp.Resources/Properties/SkiaSharpResourcesAssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("SkiaSharp.Resources")]
+[assembly: AssemblyDescription("This package adds lottie support to SkiaSharp via skottie.")]
+[assembly: AssemblyCompany("Microsoft Corporation")]
+[assembly: AssemblyProduct("SkiaSharp")]
+[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
+[assembly: NeutralResourcesLanguage("en")]
+
+[assembly: InternalsVisibleTo("SkiaSharp.Tests, PublicKey=" +
+ "002400000480000094000000060200000024000052534131000400000100010079159977d2d03a" +
+ "8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c" +
+ "3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd" +
+ "dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00" +
+ "65d016df")]
+
+[assembly: InternalsVisibleTo("SkiaSharp.Benchmarks, PublicKey=" +
+ "002400000480000094000000060200000024000052534131000400000100010079159977d2d03a" +
+ "8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c" +
+ "3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd" +
+ "dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00" +
+ "65d016df")]
+
+[assembly: AssemblyMetadata("IsTrimmable", "True")]
+
+#if __IOS__ || __TVOS__ || __MACOS__
+// This attribute allows you to mark your assemblies as “safe to link”.
+// When the attribute is present, the linker—if enabled—will process the assembly
+// even if you’re using the “Link SDK assemblies only” option, which is the default for device builds.
+#pragma warning disable CS0618 // Type or member is obsolete
+[assembly: Foundation.LinkerSafe]
+#pragma warning restore CS0618 // Type or member is obsolete
+#endif
diff --git a/binding/SkiaSharp.Resources/ResourceProvider.cs b/binding/SkiaSharp.Resources/ResourceProvider.cs
new file mode 100644
index 0000000000..5b22bc5c7d
--- /dev/null
+++ b/binding/SkiaSharp.Resources/ResourceProvider.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace SkiaSharp.Resources
+{
+ public abstract unsafe class ResourceProvider : SKObject, ISKReferenceCounted, ISKSkipObjectRegistration
+ {
+ internal ResourceProvider (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKData? Load (string resourceName) =>
+ Load ("", resourceName);
+
+ public SKData? Load (string resourcePath, string resourceName) =>
+ SKData.GetObject (ResourcesApi.skresources_resource_provider_load (Handle, resourcePath, resourceName));
+ }
+
+ public sealed class CachingResourceProvider : ResourceProvider
+ {
+ public CachingResourceProvider (ResourceProvider resourceProvider)
+ : base (Create (resourceProvider), true)
+ {
+ Referenced(this, resourceProvider);
+ }
+
+ private static IntPtr Create (ResourceProvider resourceProvider)
+ {
+ _ = resourceProvider ?? throw new ArgumentNullException (nameof (resourceProvider));
+ return ResourcesApi.skresources_caching_resource_provider_proxy_make (resourceProvider.Handle);
+ }
+ }
+
+ public sealed class DataUriResourceProvider : ResourceProvider
+ {
+ public DataUriResourceProvider (bool preDecode = false)
+ : this (null, preDecode)
+ {
+ }
+
+ public DataUriResourceProvider (ResourceProvider? fallbackProvider, bool preDecode = false)
+ : base (Create (fallbackProvider, preDecode), true)
+ {
+ Referenced (this, fallbackProvider);
+ }
+
+ private static IntPtr Create (ResourceProvider? fallbackProvider, bool preDecode = false) =>
+ ResourcesApi.skresources_data_uri_resource_provider_proxy_make (fallbackProvider?.Handle ?? IntPtr.Zero, preDecode);
+ }
+
+ public sealed class FileResourceProvider : ResourceProvider
+ {
+ public FileResourceProvider (string baseDirectory, bool preDecode = false)
+ : base (Create (baseDirectory, preDecode), true)
+ {
+ }
+
+ private static IntPtr Create (string baseDirectory, bool preDecode)
+ {
+ using var baseDir = new SKString(baseDirectory ?? throw new ArgumentNullException (nameof (baseDirectory)));
+ return ResourcesApi.skresources_file_resource_provider_make (baseDir.Handle, preDecode);
+ }
+ }
+}
diff --git a/binding/SkiaSharp.Resources/ResourcesApi.cs b/binding/SkiaSharp.Resources/ResourcesApi.cs
new file mode 100644
index 0000000000..06438cd026
--- /dev/null
+++ b/binding/SkiaSharp.Resources/ResourcesApi.cs
@@ -0,0 +1,23 @@
+#nullable disable
+
+using System;
+
+namespace SkiaSharp
+{
+ internal partial class ResourcesApi
+ {
+#if __IOS__ || __TVOS__
+ private const string SKIA = "@rpath/libSkiaSharp.framework/libSkiaSharp";
+#else
+ private const string SKIA = "libSkiaSharp";
+#endif
+
+#if USE_DELEGATES
+ private static readonly Lazy libSkiaSharpHandle =
+ new Lazy (() => LibraryLoader.LoadLocalLibrary (SKIA));
+
+ private static T GetSymbol (string name) where T : Delegate =>
+ LibraryLoader.GetSymbolDelegate (libSkiaSharpHandle.Value, name);
+#endif
+ }
+}
diff --git a/binding/SkiaSharp.Resources/ResourcesApi.generated.cs b/binding/SkiaSharp.Resources/ResourcesApi.generated.cs
new file mode 100644
index 0000000000..71eb442fcc
--- /dev/null
+++ b/binding/SkiaSharp.Resources/ResourcesApi.generated.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Runtime.InteropServices;
+
+#region Namespaces
+
+using SkiaSharp.Resources;
+
+#endregion
+
+#region Class declarations
+
+using gr_backendrendertarget_t = System.IntPtr;
+using gr_backendtexture_t = System.IntPtr;
+using gr_direct_context_t = System.IntPtr;
+using gr_glinterface_t = System.IntPtr;
+using gr_recording_context_t = System.IntPtr;
+using gr_vk_extensions_t = System.IntPtr;
+using gr_vk_memory_allocator_t = System.IntPtr;
+using gr_vkinterface_t = System.IntPtr;
+using sk_bitmap_t = System.IntPtr;
+using sk_blender_t = System.IntPtr;
+using sk_canvas_t = System.IntPtr;
+using sk_codec_t = System.IntPtr;
+using sk_colorfilter_t = System.IntPtr;
+using sk_colorspace_icc_profile_t = System.IntPtr;
+using sk_colorspace_t = System.IntPtr;
+using sk_compatpaint_t = System.IntPtr;
+using sk_data_t = System.IntPtr;
+using sk_document_t = System.IntPtr;
+using sk_drawable_t = System.IntPtr;
+using sk_flattenable_t = System.IntPtr;
+using sk_font_t = System.IntPtr;
+using sk_fontmgr_t = System.IntPtr;
+using sk_fontstyle_t = System.IntPtr;
+using sk_fontstyleset_t = System.IntPtr;
+using sk_image_t = System.IntPtr;
+using sk_imagefilter_t = System.IntPtr;
+using sk_manageddrawable_t = System.IntPtr;
+using sk_managedtracememorydump_t = System.IntPtr;
+using sk_maskfilter_t = System.IntPtr;
+using sk_nodraw_canvas_t = System.IntPtr;
+using sk_nvrefcnt_t = System.IntPtr;
+using sk_nway_canvas_t = System.IntPtr;
+using sk_opbuilder_t = System.IntPtr;
+using sk_overdraw_canvas_t = System.IntPtr;
+using sk_paint_t = System.IntPtr;
+using sk_path_effect_t = System.IntPtr;
+using sk_path_iterator_t = System.IntPtr;
+using sk_path_rawiterator_t = System.IntPtr;
+using sk_path_t = System.IntPtr;
+using sk_pathmeasure_t = System.IntPtr;
+using sk_picture_recorder_t = System.IntPtr;
+using sk_picture_t = System.IntPtr;
+using sk_pixelref_factory_t = System.IntPtr;
+using sk_pixmap_t = System.IntPtr;
+using sk_refcnt_t = System.IntPtr;
+using sk_region_cliperator_t = System.IntPtr;
+using sk_region_iterator_t = System.IntPtr;
+using sk_region_spanerator_t = System.IntPtr;
+using sk_region_t = System.IntPtr;
+using sk_rrect_t = System.IntPtr;
+using sk_runtimeeffect_t = System.IntPtr;
+using sk_shader_t = System.IntPtr;
+using sk_stream_asset_t = System.IntPtr;
+using sk_stream_filestream_t = System.IntPtr;
+using sk_stream_managedstream_t = System.IntPtr;
+using sk_stream_memorystream_t = System.IntPtr;
+using sk_stream_streamrewindable_t = System.IntPtr;
+using sk_stream_t = System.IntPtr;
+using sk_string_t = System.IntPtr;
+using sk_surface_t = System.IntPtr;
+using sk_surfaceprops_t = System.IntPtr;
+using sk_svgcanvas_t = System.IntPtr;
+using sk_textblob_builder_t = System.IntPtr;
+using sk_textblob_t = System.IntPtr;
+using sk_tracememorydump_t = System.IntPtr;
+using sk_typeface_t = System.IntPtr;
+using sk_vertices_t = System.IntPtr;
+using sk_wstream_dynamicmemorystream_t = System.IntPtr;
+using sk_wstream_filestream_t = System.IntPtr;
+using sk_wstream_managedstream_t = System.IntPtr;
+using sk_wstream_t = System.IntPtr;
+using skottie_animation_builder_t = System.IntPtr;
+using skottie_animation_t = System.IntPtr;
+using skottie_logger_t = System.IntPtr;
+using skottie_marker_observer_t = System.IntPtr;
+using skottie_property_observer_t = System.IntPtr;
+using skottie_resource_provider_t = System.IntPtr;
+using skresources_external_track_asset_t = System.IntPtr;
+using skresources_image_asset_t = System.IntPtr;
+using skresources_multi_frame_image_asset_t = System.IntPtr;
+using skresources_resource_provider_t = System.IntPtr;
+using sksg_invalidation_controller_t = System.IntPtr;
+using vk_device_t = System.IntPtr;
+using vk_instance_t = System.IntPtr;
+using vk_physical_device_features_2_t = System.IntPtr;
+using vk_physical_device_features_t = System.IntPtr;
+using vk_physical_device_t = System.IntPtr;
+using vk_queue_t = System.IntPtr;
+
+#endregion
+
+#region Functions
+
+namespace SkiaSharp
+{
+ internal unsafe partial class ResourcesApi
+ {
+ #region skresources_resource_provider.h
+
+ // skresources_resource_provider_t* skresources_caching_resource_provider_proxy_make(skresources_resource_provider_t* rp)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skresources_resource_provider_t skresources_caching_resource_provider_proxy_make (skresources_resource_provider_t rp);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skresources_resource_provider_t skresources_caching_resource_provider_proxy_make (skresources_resource_provider_t rp);
+ }
+ private static Delegates.skresources_caching_resource_provider_proxy_make skresources_caching_resource_provider_proxy_make_delegate;
+ internal static skresources_resource_provider_t skresources_caching_resource_provider_proxy_make (skresources_resource_provider_t rp) =>
+ (skresources_caching_resource_provider_proxy_make_delegate ??= GetSymbol ("skresources_caching_resource_provider_proxy_make")).Invoke (rp);
+ #endif
+
+ // skresources_resource_provider_t* skresources_data_uri_resource_provider_proxy_make(skresources_resource_provider_t* rp, bool predecode)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skresources_resource_provider_t skresources_data_uri_resource_provider_proxy_make (skresources_resource_provider_t rp, [MarshalAs (UnmanagedType.I1)] bool predecode);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skresources_resource_provider_t skresources_data_uri_resource_provider_proxy_make (skresources_resource_provider_t rp, [MarshalAs (UnmanagedType.I1)] bool predecode);
+ }
+ private static Delegates.skresources_data_uri_resource_provider_proxy_make skresources_data_uri_resource_provider_proxy_make_delegate;
+ internal static skresources_resource_provider_t skresources_data_uri_resource_provider_proxy_make (skresources_resource_provider_t rp, [MarshalAs (UnmanagedType.I1)] bool predecode) =>
+ (skresources_data_uri_resource_provider_proxy_make_delegate ??= GetSymbol ("skresources_data_uri_resource_provider_proxy_make")).Invoke (rp, predecode);
+ #endif
+
+ // skresources_resource_provider_t* skresources_file_resource_provider_make(sk_string_t* base_dir, bool predecode)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skresources_resource_provider_t skresources_file_resource_provider_make (sk_string_t base_dir, [MarshalAs (UnmanagedType.I1)] bool predecode);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skresources_resource_provider_t skresources_file_resource_provider_make (sk_string_t base_dir, [MarshalAs (UnmanagedType.I1)] bool predecode);
+ }
+ private static Delegates.skresources_file_resource_provider_make skresources_file_resource_provider_make_delegate;
+ internal static skresources_resource_provider_t skresources_file_resource_provider_make (sk_string_t base_dir, [MarshalAs (UnmanagedType.I1)] bool predecode) =>
+ (skresources_file_resource_provider_make_delegate ??= GetSymbol ("skresources_file_resource_provider_make")).Invoke (base_dir, predecode);
+ #endif
+
+ // void skresources_resource_provider_delete(skresources_resource_provider_t* instance)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skresources_resource_provider_delete (skresources_resource_provider_t instance);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skresources_resource_provider_delete (skresources_resource_provider_t instance);
+ }
+ private static Delegates.skresources_resource_provider_delete skresources_resource_provider_delete_delegate;
+ internal static void skresources_resource_provider_delete (skresources_resource_provider_t instance) =>
+ (skresources_resource_provider_delete_delegate ??= GetSymbol ("skresources_resource_provider_delete")).Invoke (instance);
+ #endif
+
+ // sk_data_t* skresources_resource_provider_load(skresources_resource_provider_t* instance, const char* path, const char* name)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t skresources_resource_provider_load (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_data_t skresources_resource_provider_load (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name);
+ }
+ private static Delegates.skresources_resource_provider_load skresources_resource_provider_load_delegate;
+ internal static sk_data_t skresources_resource_provider_load (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name) =>
+ (skresources_resource_provider_load_delegate ??= GetSymbol ("skresources_resource_provider_load")).Invoke (instance, path, name);
+ #endif
+
+ // skresources_external_track_asset_t* skresources_resource_provider_load_audio_asset(skresources_resource_provider_t* instance, const char* path, const char* name, const char* id)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skresources_external_track_asset_t skresources_resource_provider_load_audio_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skresources_external_track_asset_t skresources_resource_provider_load_audio_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id);
+ }
+ private static Delegates.skresources_resource_provider_load_audio_asset skresources_resource_provider_load_audio_asset_delegate;
+ internal static skresources_external_track_asset_t skresources_resource_provider_load_audio_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id) =>
+ (skresources_resource_provider_load_audio_asset_delegate ??= GetSymbol ("skresources_resource_provider_load_audio_asset")).Invoke (instance, path, name, id);
+ #endif
+
+ // skresources_image_asset_t* skresources_resource_provider_load_image_asset(skresources_resource_provider_t* instance, const char* path, const char* name, const char* id)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skresources_image_asset_t skresources_resource_provider_load_image_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skresources_image_asset_t skresources_resource_provider_load_image_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id);
+ }
+ private static Delegates.skresources_resource_provider_load_image_asset skresources_resource_provider_load_image_asset_delegate;
+ internal static skresources_image_asset_t skresources_resource_provider_load_image_asset (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String path, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String id) =>
+ (skresources_resource_provider_load_image_asset_delegate ??= GetSymbol ("skresources_resource_provider_load_image_asset")).Invoke (instance, path, name, id);
+ #endif
+
+ // sk_typeface_t* skresources_resource_provider_load_typeface(skresources_resource_provider_t* instance, const char* name, const char* url)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t skresources_resource_provider_load_typeface (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String url);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_typeface_t skresources_resource_provider_load_typeface (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String url);
+ }
+ private static Delegates.skresources_resource_provider_load_typeface skresources_resource_provider_load_typeface_delegate;
+ internal static sk_typeface_t skresources_resource_provider_load_typeface (skresources_resource_provider_t instance, [MarshalAs (UnmanagedType.LPStr)] String name, [MarshalAs (UnmanagedType.LPStr)] String url) =>
+ (skresources_resource_provider_load_typeface_delegate ??= GetSymbol ("skresources_resource_provider_load_typeface")).Invoke (instance, name, url);
+ #endif
+
+ // void skresources_resource_provider_ref(skresources_resource_provider_t* instance)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skresources_resource_provider_ref (skresources_resource_provider_t instance);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skresources_resource_provider_ref (skresources_resource_provider_t instance);
+ }
+ private static Delegates.skresources_resource_provider_ref skresources_resource_provider_ref_delegate;
+ internal static void skresources_resource_provider_ref (skresources_resource_provider_t instance) =>
+ (skresources_resource_provider_ref_delegate ??= GetSymbol ("skresources_resource_provider_ref")).Invoke (instance);
+ #endif
+
+ // void skresources_resource_provider_unref(skresources_resource_provider_t* instance)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skresources_resource_provider_unref (skresources_resource_provider_t instance);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skresources_resource_provider_unref (skresources_resource_provider_t instance);
+ }
+ private static Delegates.skresources_resource_provider_unref skresources_resource_provider_unref_delegate;
+ internal static void skresources_resource_provider_unref (skresources_resource_provider_t instance) =>
+ (skresources_resource_provider_unref_delegate ??= GetSymbol ("skresources_resource_provider_unref")).Invoke (instance);
+ #endif
+
+ #endregion
+
+ }
+}
+
+#endregion Functions
+
+#region Delegates
+
+#endregion
+
+#region Structs
+
+#endregion
+
+#region Enums
+
+#endregion
diff --git a/binding/SkiaSharp.Resources/SkiaSharp.Resources.csproj b/binding/SkiaSharp.Resources/SkiaSharp.Resources.csproj
new file mode 100644
index 0000000000..87ee248726
--- /dev/null
+++ b/binding/SkiaSharp.Resources/SkiaSharp.Resources.csproj
@@ -0,0 +1,18 @@
+
+
+ $(AllTargetFrameworks)
+ SkiaSharp.Resources
+ SkiaSharp.Resources
+ SkiaSharp.Resources
+ SkiaSharp Resource Providers
+ SkiaSharp Skottie provides a Lottie implementation using the SkiaSharp library.
+ skottie;lottie
+ enable
+
+
+ $(DefineConstants);USE_DELEGATES
+
+
+
+
+
\ No newline at end of file
diff --git a/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs b/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs
index a3b6ab1f96..36d57c6fbc 100644
--- a/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs
+++ b/binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs
@@ -18,6 +18,7 @@
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
+using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;
@@ -85,6 +86,10 @@
using skottie_marker_observer_t = System.IntPtr;
using skottie_property_observer_t = System.IntPtr;
using skottie_resource_provider_t = System.IntPtr;
+using skresources_external_track_asset_t = System.IntPtr;
+using skresources_image_asset_t = System.IntPtr;
+using skresources_multi_frame_image_asset_t = System.IntPtr;
+using skresources_resource_provider_t = System.IntPtr;
using sksg_invalidation_controller_t = System.IntPtr;
using vk_device_t = System.IntPtr;
using vk_instance_t = System.IntPtr;
diff --git a/binding/SkiaSharp.Skottie/Animation.cs b/binding/SkiaSharp.Skottie/Animation.cs
index a6ad5ae5b9..a7360d7328 100644
--- a/binding/SkiaSharp.Skottie/Animation.cs
+++ b/binding/SkiaSharp.Skottie/Animation.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using SkiaSharp.Resources;
using SkiaSharp.SceneGraph;
namespace SkiaSharp.Skottie
@@ -20,6 +21,11 @@ void ISKNonVirtualReferenceCounted.UnreferenceNative ()
protected override void DisposeNative ()
=> SkottieApi.skottie_animation_delete (Handle);
+ // AnimationBuilder
+
+ public static AnimationBuilder CreateBuilder (AnimationBuilderFlags flags = AnimationBuilderFlags.None) =>
+ new AnimationBuilder (flags);
+
// Parse
public static Animation? Parse (string json) =>
@@ -77,6 +83,7 @@ public static bool TryCreate (SKData data, [System.Diagnostics.CodeAnalysis.NotN
fixed (byte* ptr = span) {
animation = GetObject (SkottieApi.skottie_animation_make_from_data (ptr, (IntPtr)span.Length));
+ GC.KeepAlive(data);
return animation != null;
}
}
diff --git a/binding/SkiaSharp.Skottie/AnimationBuilder.cs b/binding/SkiaSharp.Skottie/AnimationBuilder.cs
new file mode 100644
index 0000000000..b84f563a36
--- /dev/null
+++ b/binding/SkiaSharp.Skottie/AnimationBuilder.cs
@@ -0,0 +1,88 @@
+using System;
+using System.IO;
+using SkiaSharp.Resources;
+
+namespace SkiaSharp.Skottie
+{
+ public sealed unsafe class AnimationBuilder : SKObject, ISKSkipObjectRegistration
+ {
+ internal AnimationBuilder (AnimationBuilderFlags flags)
+ : this (SkottieApi.skottie_animation_builder_new (flags), true)
+ {
+ }
+
+ internal AnimationBuilder (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public AnimationBuilder SetFontManager (SKFontManager fontManager)
+ {
+ _ = fontManager ?? throw new ArgumentNullException (nameof (fontManager));
+ SkottieApi.skottie_animation_builder_set_font_manager (Handle, fontManager.Handle);
+ Referenced (this, fontManager);
+ return this;
+ }
+
+ public AnimationBuilder SetResourceProvider (ResourceProvider resourceProvider)
+ {
+ _ = resourceProvider ?? throw new ArgumentNullException (nameof (resourceProvider));
+ SkottieApi.skottie_animation_builder_set_resource_provider (Handle, resourceProvider.Handle);
+ Referenced (this, resourceProvider);
+ return this;
+ }
+
+ public AnimationBuilderStats Stats
+ {
+ get
+ {
+ AnimationBuilderStats stats;
+ SkottieApi.skottie_animation_builder_get_stats (Handle, &stats);
+ return stats;
+ }
+ }
+
+ public Animation? Build (Stream stream)
+ {
+ _ = stream ?? throw new ArgumentNullException (nameof (stream));
+
+ using var data = SKData.Create (stream);
+ return Build (data);
+ }
+
+ public Animation? Build (SKStream stream)
+ {
+ _ = stream ?? throw new ArgumentNullException (nameof (stream));
+
+ using var data = SKData.Create (stream);
+ return Build (data);
+ }
+
+ public Animation? Build (SKData data)
+ {
+ _ = data ?? throw new ArgumentNullException (nameof (data));
+
+ var preamble = Utils.GetPreambleSize (data);
+ var span = data.AsSpan ().Slice (preamble);
+
+ fixed (byte* ptr = span) {
+ try {
+ return Animation.GetObject (SkottieApi.skottie_animation_builder_make_from_data (Handle, ptr, (IntPtr)span.Length));
+ } finally {
+ GC.KeepAlive(data);
+ }
+ }
+ }
+
+ public Animation? Build (string path)
+ {
+ _ = path ?? throw new ArgumentNullException (nameof (path));
+
+ using var data = SKData.Create (path);
+ return Build (data);
+ }
+
+ protected override void DisposeNative ()
+ => SkottieApi.skottie_animation_builder_delete (Handle);
+ }
+}
diff --git a/binding/SkiaSharp.Skottie/AnimationBuilderStats.cs b/binding/SkiaSharp.Skottie/AnimationBuilderStats.cs
new file mode 100644
index 0000000000..42d9e48efd
--- /dev/null
+++ b/binding/SkiaSharp.Skottie/AnimationBuilderStats.cs
@@ -0,0 +1,21 @@
+
+using System;
+
+namespace SkiaSharp.Skottie
+{
+ public partial struct AnimationBuilderStats
+ {
+ public readonly TimeSpan TotalLoadTime =>
+ TimeSpan.FromMilliseconds (fTotalLoadTimeMS);
+
+ public readonly TimeSpan JsonParseTime =>
+ TimeSpan.FromMilliseconds (fJsonParseTimeMS);
+
+ public readonly TimeSpan SceneParseTime =>
+ TimeSpan.FromMilliseconds (fSceneParseTimeMS);
+
+ public readonly int JsonSize => (int)fJsonSize;
+
+ public readonly int AnimatorCount => (int)fAnimatorCount;
+ }
+}
diff --git a/binding/SkiaSharp.Skottie/SkiaSharp.Skottie.csproj b/binding/SkiaSharp.Skottie/SkiaSharp.Skottie.csproj
index 8947f56b39..4fd4ef3112 100644
--- a/binding/SkiaSharp.Skottie/SkiaSharp.Skottie.csproj
+++ b/binding/SkiaSharp.Skottie/SkiaSharp.Skottie.csproj
@@ -15,5 +15,6 @@
+
\ No newline at end of file
diff --git a/binding/SkiaSharp.Skottie/SkottieApi.generated.cs b/binding/SkiaSharp.Skottie/SkottieApi.generated.cs
index 8bcc631ec4..38f281ace3 100644
--- a/binding/SkiaSharp.Skottie/SkottieApi.generated.cs
+++ b/binding/SkiaSharp.Skottie/SkottieApi.generated.cs
@@ -18,6 +18,7 @@
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
+using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;
@@ -85,6 +86,10 @@
using skottie_marker_observer_t = System.IntPtr;
using skottie_property_observer_t = System.IntPtr;
using skottie_resource_provider_t = System.IntPtr;
+using skresources_external_track_asset_t = System.IntPtr;
+using skresources_image_asset_t = System.IntPtr;
+using skresources_multi_frame_image_asset_t = System.IntPtr;
+using skresources_resource_provider_t = System.IntPtr;
using sksg_invalidation_controller_t = System.IntPtr;
using vk_device_t = System.IntPtr;
using vk_instance_t = System.IntPtr;
@@ -103,6 +108,132 @@ internal unsafe partial class SkottieApi
{
#region skottie_animation.h
+ // void skottie_animation_builder_delete(skottie_animation_builder_t* instance)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skottie_animation_builder_delete (skottie_animation_builder_t instance);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skottie_animation_builder_delete (skottie_animation_builder_t instance);
+ }
+ private static Delegates.skottie_animation_builder_delete skottie_animation_builder_delete_delegate;
+ internal static void skottie_animation_builder_delete (skottie_animation_builder_t instance) =>
+ (skottie_animation_builder_delete_delegate ??= GetSymbol ("skottie_animation_builder_delete")).Invoke (instance);
+ #endif
+
+ // void skottie_animation_builder_get_stats(skottie_animation_builder_t* instance, skottie_animation_builder_stats_t* stats)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skottie_animation_builder_get_stats (skottie_animation_builder_t instance, AnimationBuilderStats* stats);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skottie_animation_builder_get_stats (skottie_animation_builder_t instance, AnimationBuilderStats* stats);
+ }
+ private static Delegates.skottie_animation_builder_get_stats skottie_animation_builder_get_stats_delegate;
+ internal static void skottie_animation_builder_get_stats (skottie_animation_builder_t instance, AnimationBuilderStats* stats) =>
+ (skottie_animation_builder_get_stats_delegate ??= GetSymbol ("skottie_animation_builder_get_stats")).Invoke (instance, stats);
+ #endif
+
+ // skottie_animation_t* skottie_animation_builder_make_from_data(skottie_animation_builder_t* instance, const char* data, size_t length)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skottie_animation_t skottie_animation_builder_make_from_data (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skottie_animation_t skottie_animation_builder_make_from_data (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length);
+ }
+ private static Delegates.skottie_animation_builder_make_from_data skottie_animation_builder_make_from_data_delegate;
+ internal static skottie_animation_t skottie_animation_builder_make_from_data (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length) =>
+ (skottie_animation_builder_make_from_data_delegate ??= GetSymbol ("skottie_animation_builder_make_from_data")).Invoke (instance, data, length);
+ #endif
+
+ // skottie_animation_t* skottie_animation_builder_make_from_file(skottie_animation_builder_t* instance, const char* path)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skottie_animation_t skottie_animation_builder_make_from_file (skottie_animation_builder_t instance, /* char */ void* path);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skottie_animation_t skottie_animation_builder_make_from_file (skottie_animation_builder_t instance, /* char */ void* path);
+ }
+ private static Delegates.skottie_animation_builder_make_from_file skottie_animation_builder_make_from_file_delegate;
+ internal static skottie_animation_t skottie_animation_builder_make_from_file (skottie_animation_builder_t instance, /* char */ void* path) =>
+ (skottie_animation_builder_make_from_file_delegate ??= GetSymbol ("skottie_animation_builder_make_from_file")).Invoke (instance, path);
+ #endif
+
+ // skottie_animation_t* skottie_animation_builder_make_from_stream(skottie_animation_builder_t* instance, sk_stream_t* stream)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skottie_animation_t skottie_animation_builder_make_from_stream (skottie_animation_builder_t instance, sk_stream_t stream);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skottie_animation_t skottie_animation_builder_make_from_stream (skottie_animation_builder_t instance, sk_stream_t stream);
+ }
+ private static Delegates.skottie_animation_builder_make_from_stream skottie_animation_builder_make_from_stream_delegate;
+ internal static skottie_animation_t skottie_animation_builder_make_from_stream (skottie_animation_builder_t instance, sk_stream_t stream) =>
+ (skottie_animation_builder_make_from_stream_delegate ??= GetSymbol ("skottie_animation_builder_make_from_stream")).Invoke (instance, stream);
+ #endif
+
+ // skottie_animation_t* skottie_animation_builder_make_from_string(skottie_animation_builder_t* instance, const char* data, size_t length)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skottie_animation_t skottie_animation_builder_make_from_string (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skottie_animation_t skottie_animation_builder_make_from_string (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length);
+ }
+ private static Delegates.skottie_animation_builder_make_from_string skottie_animation_builder_make_from_string_delegate;
+ internal static skottie_animation_t skottie_animation_builder_make_from_string (skottie_animation_builder_t instance, /* char */ void* data, /* size_t */ IntPtr length) =>
+ (skottie_animation_builder_make_from_string_delegate ??= GetSymbol ("skottie_animation_builder_make_from_string")).Invoke (instance, data, length);
+ #endif
+
+ // skottie_animation_builder_t* skottie_animation_builder_new(skottie_animation_builder_flags_t flags)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern skottie_animation_builder_t skottie_animation_builder_new (AnimationBuilderFlags flags);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate skottie_animation_builder_t skottie_animation_builder_new (AnimationBuilderFlags flags);
+ }
+ private static Delegates.skottie_animation_builder_new skottie_animation_builder_new_delegate;
+ internal static skottie_animation_builder_t skottie_animation_builder_new (AnimationBuilderFlags flags) =>
+ (skottie_animation_builder_new_delegate ??= GetSymbol ("skottie_animation_builder_new")).Invoke (flags);
+ #endif
+
+ // void skottie_animation_builder_set_font_manager(skottie_animation_builder_t* instance, sk_fontmgr_t* fontManager)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skottie_animation_builder_set_font_manager (skottie_animation_builder_t instance, sk_fontmgr_t fontManager);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skottie_animation_builder_set_font_manager (skottie_animation_builder_t instance, sk_fontmgr_t fontManager);
+ }
+ private static Delegates.skottie_animation_builder_set_font_manager skottie_animation_builder_set_font_manager_delegate;
+ internal static void skottie_animation_builder_set_font_manager (skottie_animation_builder_t instance, sk_fontmgr_t fontManager) =>
+ (skottie_animation_builder_set_font_manager_delegate ??= GetSymbol ("skottie_animation_builder_set_font_manager")).Invoke (instance, fontManager);
+ #endif
+
+ // void skottie_animation_builder_set_resource_provider(skottie_animation_builder_t* instance, skottie_resource_provider_t* resourceProvider)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void skottie_animation_builder_set_resource_provider (skottie_animation_builder_t instance, skottie_resource_provider_t resourceProvider);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void skottie_animation_builder_set_resource_provider (skottie_animation_builder_t instance, skottie_resource_provider_t resourceProvider);
+ }
+ private static Delegates.skottie_animation_builder_set_resource_provider skottie_animation_builder_set_resource_provider_delegate;
+ internal static void skottie_animation_builder_set_resource_provider (skottie_animation_builder_t instance, skottie_resource_provider_t resourceProvider) =>
+ (skottie_animation_builder_set_resource_provider_delegate ??= GetSymbol ("skottie_animation_builder_set_resource_provider")).Invoke (instance, resourceProvider);
+ #endif
+
// void skottie_animation_delete(skottie_animation_t* instance)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -201,20 +332,6 @@ internal static void skottie_animation_get_version (skottie_animation_t instance
(skottie_animation_get_version_delegate ??= GetSymbol ("skottie_animation_get_version")).Invoke (instance, version);
#endif
- // void skottie_animation_keepalive()
- #if !USE_DELEGATES
- [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
- internal static extern void skottie_animation_keepalive ();
- #else
- private partial class Delegates {
- [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
- internal delegate void skottie_animation_keepalive ();
- }
- private static Delegates.skottie_animation_keepalive skottie_animation_keepalive_delegate;
- internal static void skottie_animation_keepalive () =>
- (skottie_animation_keepalive_delegate ??= GetSymbol ("skottie_animation_keepalive")).Invoke ();
- #endif
-
// skottie_animation_t* skottie_animation_make_from_data(const char* data, size_t length)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -382,12 +499,68 @@ internal static void skottie_animation_unref (skottie_animation_t instance) =>
#region Structs
+namespace SkiaSharp.Skottie {
+
+ // skottie_animation_builder_stats_t
+ [StructLayout (LayoutKind.Sequential)]
+ public readonly unsafe partial struct AnimationBuilderStats : IEquatable {
+ // public float fTotalLoadTimeMS
+ private readonly Single fTotalLoadTimeMS;
+
+ // public float fJsonParseTimeMS
+ private readonly Single fJsonParseTimeMS;
+
+ // public float fSceneParseTimeMS
+ private readonly Single fSceneParseTimeMS;
+
+ // public size_t fJsonSize
+ private readonly /* size_t */ IntPtr fJsonSize;
+
+ // public size_t fAnimatorCount
+ private readonly /* size_t */ IntPtr fAnimatorCount;
+
+ public readonly bool Equals (AnimationBuilderStats obj) =>
+ fTotalLoadTimeMS == obj.fTotalLoadTimeMS && fJsonParseTimeMS == obj.fJsonParseTimeMS && fSceneParseTimeMS == obj.fSceneParseTimeMS && fJsonSize == obj.fJsonSize && fAnimatorCount == obj.fAnimatorCount;
+
+ public readonly override bool Equals (object obj) =>
+ obj is AnimationBuilderStats f && Equals (f);
+
+ public static bool operator == (AnimationBuilderStats left, AnimationBuilderStats right) =>
+ left.Equals (right);
+
+ public static bool operator != (AnimationBuilderStats left, AnimationBuilderStats right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fTotalLoadTimeMS);
+ hash.Add (fJsonParseTimeMS);
+ hash.Add (fSceneParseTimeMS);
+ hash.Add (fJsonSize);
+ hash.Add (fAnimatorCount);
+ return hash.ToHashCode ();
+ }
+
+ }
+}
+
#endregion
#region Enums
namespace SkiaSharp.Skottie {
+ // skottie_animation_builder_flags_t
+ public enum AnimationBuilderFlags {
+ // NONE_SKOTTIE_ANIMATION_BUILDER_FLAGS = 0
+ None = 0,
+ // DEFER_IMAGE_LOADING_SKOTTIE_ANIMATION_BUILDER_FLAGS = 0x01
+ DeferImageLoading = 1,
+ // PREFER_EMBEDDED_FONTS_SKOTTIE_ANIMATION_BUILDER_FLAGS = 0x02
+ PreferEmbeddedFonts = 2,
+ }
+
// skottie_animation_renderflags_t
[Flags]
public enum AnimationRenderFlags {
diff --git a/binding/SkiaSharp/GRBackendTexture.cs b/binding/SkiaSharp/GRBackendTexture.cs
index 603731f457..254cc3c708 100644
--- a/binding/SkiaSharp/GRBackendTexture.cs
+++ b/binding/SkiaSharp/GRBackendTexture.cs
@@ -25,8 +25,6 @@ public GRBackendTexture (int width, int height, GRVkImageInfo vkInfo)
CreateVulkan (width, height, vkInfo);
}
-#if __IOS__ || __MACOS__
-
public GRBackendTexture (int width, int height, bool mipmapped, GRMtlTextureInfo mtlInfo)
: this (IntPtr.Zero, true)
{
@@ -38,8 +36,6 @@ public GRBackendTexture (int width, int height, bool mipmapped, GRMtlTextureInfo
}
}
-#endif
-
private void CreateGl (int width, int height, bool mipmapped, GRGlTextureInfo glInfo)
{
Handle = SkiaApi.gr_backendtexture_new_gl (width, height, mipmapped, &glInfo);
diff --git a/binding/SkiaSharp/GRContext.cs b/binding/SkiaSharp/GRContext.cs
index 70a50e67a4..55071e4187 100644
--- a/binding/SkiaSharp/GRContext.cs
+++ b/binding/SkiaSharp/GRContext.cs
@@ -63,8 +63,6 @@ public static GRContext CreateVulkan (GRVkBackendContext backendContext, GRConte
}
}
-#if __IOS__ || __MACOS__
-
// CreateMetal
public static GRContext CreateMetal (GRMtlBackendContext backendContext) =>
@@ -75,19 +73,17 @@ public static GRContext CreateMetal (GRMtlBackendContext backendContext, GRConte
if (backendContext == null)
throw new ArgumentNullException (nameof (backendContext));
- var device = backendContext.Device;
- var queue = backendContext.Queue;
+ var device = backendContext.DeviceHandle;
+ var queue = backendContext.QueueHandle;
if (options == null) {
- return GetObject (SkiaApi.gr_direct_context_make_metal ((void*)(IntPtr)device.Handle, (void*)(IntPtr)queue.Handle));
+ return GetObject (SkiaApi.gr_direct_context_make_metal ((void*)device, (void*)queue));
} else {
var opts = options.ToNative ();
- return GetObject (SkiaApi.gr_direct_context_make_metal_with_options ((void*)(IntPtr)device.Handle, (void*)(IntPtr)queue.Handle, &opts));
+ return GetObject (SkiaApi.gr_direct_context_make_metal_with_options ((void*)device, (void*)queue, &opts));
}
}
-#endif
-
//
public override GRBackend Backend => base.Backend;
diff --git a/binding/SkiaSharp/GRDefinitions.cs b/binding/SkiaSharp/GRDefinitions.cs
index 54c9a46ad9..ed6c3facb0 100644
--- a/binding/SkiaSharp/GRDefinitions.cs
+++ b/binding/SkiaSharp/GRDefinitions.cs
@@ -74,24 +74,48 @@ public GRGlTextureInfo (uint target, uint id, uint format)
}
}
-#if __IOS__ || __MACOS__
-
public unsafe partial struct GRMtlTextureInfo
{
+ private IntPtr _textureHandle;
+
+ public GRMtlTextureInfo (IntPtr textureHandle)
+ {
+ TextureHandle = textureHandle;
+ }
+
+ public IntPtr TextureHandle {
+ readonly get => _textureHandle;
+ set {
+ _textureHandle = value;
+#if __IOS__ || __MACOS__
+ _texture = null;
+#endif
+ }
+ }
+
+#if __IOS__ || __MACOS__
+ private Metal.IMTLTexture _texture;
public GRMtlTextureInfo (Metal.IMTLTexture texture)
{
Texture = texture;
}
- public Metal.IMTLTexture Texture { get; set; }
+ public Metal.IMTLTexture Texture {
+ readonly get => _texture;
+ set {
+ _texture = value;
+ _textureHandle = _texture.Handle;
+ }
+ }
+#endif
internal GRMtlTextureInfoNative ToNative () =>
new GRMtlTextureInfoNative {
- fTexture = (void*)(IntPtr)Texture.Handle
+ fTexture = (void*)TextureHandle
};
public readonly bool Equals (GRMtlTextureInfo obj) =>
- Texture == obj.Texture;
+ TextureHandle == obj.TextureHandle;
public readonly override bool Equals (object obj) =>
obj is GRMtlTextureInfo f && Equals (f);
@@ -105,13 +129,11 @@ public readonly override bool Equals (object obj) =>
public readonly override int GetHashCode ()
{
var hash = new HashCode ();
- hash.Add (Texture);
+ hash.Add (TextureHandle);
return hash.ToHashCode ();
}
}
-#endif
-
public static partial class SkiaExtensions
{
public static uint ToGlSizedFormat (this SKColorType colorType) =>
diff --git a/binding/SkiaSharp/GRMtlBackendContext.cs b/binding/SkiaSharp/GRMtlBackendContext.cs
index aba9670b9a..9c2aa28112 100644
--- a/binding/SkiaSharp/GRMtlBackendContext.cs
+++ b/binding/SkiaSharp/GRMtlBackendContext.cs
@@ -1,16 +1,56 @@
#nullable disable
-#if __IOS__ || __MACOS__
using System;
+#if __IOS__ || __MACOS__
using Metal;
+#endif
namespace SkiaSharp
{
public class GRMtlBackendContext : IDisposable
{
- public IMTLDevice Device { get; set; }
+ private IntPtr _deviceHandle, _queueHandle;
+
+ public IntPtr DeviceHandle {
+ get => _deviceHandle;
+ set {
+ _deviceHandle = value;
+#if __IOS__ || __MACOS__
+ _device = null;
+#endif
+ }
+ }
+
+ public IntPtr QueueHandle {
+ get => _queueHandle;
+ set {
+ _queueHandle = value;
+#if __IOS__ || __MACOS__
+ _queue = null;
+#endif
+ }
+ }
- public IMTLCommandQueue Queue { get; set; }
+#if __IOS__ || __MACOS__
+ private IMTLDevice _device;
+ private IMTLCommandQueue _queue;
+
+ public IMTLDevice Device {
+ get => _device;
+ set {
+ _device = value;
+ _deviceHandle = _device.Handle;
+ }
+ }
+
+ public IMTLCommandQueue Queue {
+ get => _queue;
+ set {
+ _queue = value;
+ _queueHandle = _queue.Handle;
+ }
+ }
+#endif
protected virtual void Dispose (bool disposing)
{
@@ -23,4 +63,3 @@ public void Dispose ()
}
}
}
-#endif
diff --git a/binding/SkiaSharp/Properties/SkiaSharpAssemblyInfo.cs b/binding/SkiaSharp/Properties/SkiaSharpAssemblyInfo.cs
index 5b6906f879..8d994ffb6c 100644
--- a/binding/SkiaSharp/Properties/SkiaSharpAssemblyInfo.cs
+++ b/binding/SkiaSharp/Properties/SkiaSharpAssemblyInfo.cs
@@ -45,6 +45,13 @@
"dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00" +
"65d016df")]
+[assembly: InternalsVisibleTo("SkiaSharp.Resources, PublicKey=" +
+ "002400000480000094000000060200000024000052534131000400000100010079159977d2d03a" +
+ "8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c" +
+ "3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fd" +
+ "dafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef00" +
+ "65d016df")]
+
[assembly: AssemblyMetadata("IsTrimmable", "True")]
#if __IOS__ || __TVOS__ || __MACOS__
diff --git a/binding/SkiaSharp/SKBlender.cs b/binding/SkiaSharp/SKBlender.cs
new file mode 100644
index 0000000000..e4a82adede
--- /dev/null
+++ b/binding/SkiaSharp/SKBlender.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+
+namespace SkiaSharp;
+
+public unsafe class SKBlender : SKObject, ISKReferenceCounted
+{
+ private static readonly Dictionary blendModeBlenders;
+
+ static SKBlender ()
+ {
+ // TODO: This is not the best way to do this as it will create a lot of objects that
+ // might not be needed, but it is the only way to ensure that the static
+ // instances are created before any access is made to them.
+ // See more info: SKObject.EnsureStaticInstanceAreInitialized()
+
+ var modes = Enum.GetValues (typeof (SKBlendMode));
+ blendModeBlenders = new Dictionary (modes.Length);
+ foreach (SKBlendMode mode in modes)
+ {
+ blendModeBlenders [mode] = new SKBlenderStatic (SkiaApi.sk_blender_new_mode (mode));
+ }
+ }
+
+ internal static void EnsureStaticInstanceAreInitialized ()
+ {
+ // IMPORTANT: do not remove to ensure that the static instances
+ // are initialized before any access is made to them
+ }
+
+ internal SKBlender(IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static SKBlender CreateBlendMode (SKBlendMode mode)
+ {
+ if (!blendModeBlenders.TryGetValue (mode, out var value))
+ throw new ArgumentOutOfRangeException (nameof (mode));
+ return value;
+ }
+
+ public static SKBlender CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor) =>
+ GetObject (SkiaApi.sk_blender_new_arithmetic (k1, k2, k3, k4, enforcePMColor));
+
+ internal static SKBlender GetObject (IntPtr handle) =>
+ GetOrAddObject (handle, (h, o) => new SKBlender (h, o));
+
+ //
+
+ private sealed class SKBlenderStatic : SKBlender
+ {
+ internal SKBlenderStatic (IntPtr x)
+ : base (x, false)
+ {
+ }
+
+ protected override void Dispose (bool disposing) { }
+ }
+}
diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs
index b4124c5b96..e5a0dbfc68 100644
--- a/binding/SkiaSharp/SKCanvas.cs
+++ b/binding/SkiaSharp/SKCanvas.cs
@@ -856,6 +856,10 @@ public void ResetMatrix ()
public void SetMatrix (in SKMatrix matrix) =>
SetMatrix ((SKMatrix44)matrix);
+ [Obsolete("Use SetMatrix(in SKMatrix) instead.", true)]
+ public void SetMatrix (SKMatrix matrix) =>
+ SetMatrix (in matrix);
+
public void SetMatrix (in SKMatrix44 matrix)
{
fixed (SKMatrix44* ptr = &matrix) {
diff --git a/binding/SkiaSharp/SKColorSpace.cs b/binding/SkiaSharp/SKColorSpace.cs
index 1b5680df8f..a639dac46f 100644
--- a/binding/SkiaSharp/SKColorSpace.cs
+++ b/binding/SkiaSharp/SKColorSpace.cs
@@ -12,6 +12,11 @@ public unsafe class SKColorSpace : SKObject, ISKNonVirtualReferenceCounted
static SKColorSpace ()
{
+ // TODO: This is not the best way to do this as it will create a lot of objects that
+ // might not be needed, but it is the only way to ensure that the static
+ // instances are created before any access is made to them.
+ // See more info: SKObject.EnsureStaticInstanceAreInitialized()
+
srgb = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb ());
srgbLinear = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb_linear ());
}
diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs
index 5bb53d47ca..af8f1f857f 100644
--- a/binding/SkiaSharp/SKData.cs
+++ b/binding/SkiaSharp/SKData.cs
@@ -19,6 +19,11 @@ public unsafe class SKData : SKObject, ISKNonVirtualReferenceCounted
static SKData ()
{
+ // TODO: This is not the best way to do this as it will create a lot of objects that
+ // might not be needed, but it is the only way to ensure that the static
+ // instances are created before any access is made to them.
+ // See more info: SKObject.EnsureStaticInstanceAreInitialized()
+
empty = new SKDataStatic (SkiaApi.sk_data_new_empty ());
}
@@ -156,7 +161,11 @@ public static SKData Create (SKStream stream, int length)
if (stream == null)
throw new ArgumentNullException (nameof (stream));
- return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ try {
+ return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ } finally {
+ GC.KeepAlive(stream);
+ }
}
public static SKData Create (SKStream stream, ulong length)
@@ -164,7 +173,11 @@ public static SKData Create (SKStream stream, ulong length)
if (stream == null)
throw new ArgumentNullException (nameof (stream));
- return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ try {
+ return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ } finally {
+ GC.KeepAlive(stream);
+ }
}
public static SKData Create (SKStream stream, long length)
@@ -172,7 +185,11 @@ public static SKData Create (SKStream stream, long length)
if (stream == null)
throw new ArgumentNullException (nameof (stream));
- return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ try {
+ return GetObject (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr)length));
+ } finally {
+ GC.KeepAlive(stream);
+ }
}
public static SKData Create (IntPtr address, int length)
diff --git a/binding/SkiaSharp/SKFontManager.cs b/binding/SkiaSharp/SKFontManager.cs
index 4fa74bac7f..737b875155 100644
--- a/binding/SkiaSharp/SKFontManager.cs
+++ b/binding/SkiaSharp/SKFontManager.cs
@@ -14,6 +14,11 @@ public unsafe class SKFontManager : SKObject, ISKReferenceCounted
static SKFontManager ()
{
+ // TODO: This is not the best way to do this as it will create a lot of objects that
+ // might not be needed, but it is the only way to ensure that the static
+ // instances are created before any access is made to them.
+ // See more info: SKObject.EnsureStaticInstanceAreInitialized()
+
defaultManager = new SKFontManagerStatic (SkiaApi.sk_fontmgr_ref_default ());
}
diff --git a/binding/SkiaSharp/SKImage.cs b/binding/SkiaSharp/SKImage.cs
index 834b05519b..4f4f3ff612 100644
--- a/binding/SkiaSharp/SKImage.cs
+++ b/binding/SkiaSharp/SKImage.cs
@@ -415,6 +415,26 @@ public SKShader ToShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamp
private SKShader ToShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions sampling, SKMatrix* localMatrix) =>
SKShader.GetObject (SkiaApi.sk_image_make_shader (Handle, tileX, tileY, &sampling, localMatrix));
+ // ToRawShader
+
+ public SKShader ToRawShader () =>
+ ToRawShader (SKShaderTileMode.Clamp, SKShaderTileMode.Clamp, SKSamplingOptions.Default, null);
+
+ public SKShader ToRawShader (SKShaderTileMode tileX, SKShaderTileMode tileY) =>
+ ToRawShader (tileX, tileY, SKSamplingOptions.Default, null);
+
+ public SKShader ToRawShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKMatrix localMatrix) =>
+ ToRawShader (tileX, tileY, SKSamplingOptions.Default, &localMatrix);
+
+ public SKShader ToRawShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions sampling) =>
+ ToRawShader (tileX, tileY, sampling, null);
+
+ public SKShader ToRawShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions sampling, SKMatrix localMatrix) =>
+ ToRawShader (tileX, tileY, sampling, &localMatrix);
+
+ private SKShader ToRawShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions sampling, SKMatrix* localMatrix) =>
+ SKShader.GetObject (SkiaApi.sk_image_make_raw_shader (Handle, tileX, tileY, &sampling, localMatrix));
+
// PeekPixels
public bool PeekPixels (SKPixmap pixmap)
diff --git a/binding/SkiaSharp/SKImageFilter.cs b/binding/SkiaSharp/SKImageFilter.cs
index 91f106f923..45eea572e3 100644
--- a/binding/SkiaSharp/SKImageFilter.cs
+++ b/binding/SkiaSharp/SKImageFilter.cs
@@ -14,6 +14,14 @@ protected override void Dispose (bool disposing) =>
// CreateMatrix
+ [Obsolete("Use SetMatrix(in SKMatrix) instead.", true)]
+ public static SKImageFilter CreateMatrix (SKMatrix matrix) =>
+ CreateMatrix (in matrix);
+
+ [Obsolete("Use SetMatrix(in SKMatrix, SKSamplingOptions, SKImageFilter) instead.", true)]
+ public static SKImageFilter CreateMatrix (SKMatrix matrix, SKFilterQuality quality, SKImageFilter? input) =>
+ CreateMatrix (in matrix, quality.ToSamplingOptions (), input);
+
public static SKImageFilter CreateMatrix (in SKMatrix matrix) =>
CreateMatrix (matrix, SKSamplingOptions.Default, null);
@@ -26,18 +34,6 @@ public static SKImageFilter CreateMatrix (in SKMatrix matrix, SKSamplingOptions
return GetObject (SkiaApi.sk_imagefilter_new_matrix_transform (m, &sampling, input?.Handle ?? IntPtr.Zero));
}
-
- // CreateAlphaThreshold
-
- public static SKImageFilter CreateAlphaThreshold (SKRegion region, float innerThreshold, float outerThreshold) =>
- CreateAlphaThreshold (region, innerThreshold, outerThreshold, null);
-
- public static SKImageFilter CreateAlphaThreshold (SKRegion region, float innerThreshold, float outerThreshold, SKImageFilter? input)
- {
- _ = region ?? throw new ArgumentNullException (nameof (region));
- return GetObject (SkiaApi.sk_imagefilter_new_alpha_threshold (region.Handle, innerThreshold, outerThreshold, input?.Handle ?? IntPtr.Zero));
- }
-
// CreateBlur
public static SKImageFilter CreateBlur (float sigmaX, float sigmaY) =>
@@ -345,6 +341,23 @@ public static SKImageFilter CreateBlendMode (SKBlendMode mode, SKImageFilter? ba
private static SKImageFilter CreateBlendMode (SKBlendMode mode, SKImageFilter? background, SKImageFilter? foreground, SKRect* cropRect) =>
GetObject (SkiaApi.sk_imagefilter_new_blend (mode, background?.Handle ?? IntPtr.Zero, foreground?.Handle ?? IntPtr.Zero, cropRect));
+ // CreateBlendMode (Blender)
+
+ public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background) =>
+ CreateBlendMode (blender, background, null, null);
+
+ public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground) =>
+ CreateBlendMode (blender, background, foreground, null);
+
+ public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground, SKRect cropRect) =>
+ CreateBlendMode (blender, background, foreground, &cropRect);
+
+ private static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground, SKRect* cropRect)
+ {
+ _ = blender ?? throw new ArgumentNullException (nameof (blender));
+ return GetObject (SkiaApi.sk_imagefilter_new_blender (blender.Handle, background?.Handle ?? IntPtr.Zero, foreground?.Handle ?? IntPtr.Zero, cropRect));
+ }
+
// CreateArithmetic
public static SKImageFilter CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor, SKImageFilter? background) =>
@@ -376,6 +389,10 @@ public static SKImageFilter CreateImage (SKImage image, SKRect src, SKRect dst,
return GetObject (SkiaApi.sk_imagefilter_new_image (image.Handle, &src, &dst, &sampling));
}
+ [Obsolete("Use CreateImage(SKImage, SKRect, SKRect, SKSamplingOptions) instead.", true)]
+ public static SKImageFilter CreateImage (SKImage image, SKRect src, SKRect dst, SKFilterQuality filterQuality) =>
+ CreateImage (image, src, dst, filterQuality.ToSamplingOptions ());
+
// CreateMagnifier
public static SKImageFilter CreateMagnifier (SKRect lensBounds, float zoomAmount, float inset, SKSamplingOptions sampling) =>
@@ -390,6 +407,22 @@ public static SKImageFilter CreateMagnifier (SKRect lensBounds, float zoomAmount
private static SKImageFilter CreateMagnifier (SKRect lensBounds, float zoomAmount, float inset, SKSamplingOptions sampling, SKImageFilter? input, SKRect* cropRect) =>
GetObject (SkiaApi.sk_imagefilter_new_magnifier (&lensBounds, zoomAmount, inset, &sampling, input?.Handle ?? IntPtr.Zero, cropRect));
+ // CreatePaint
+
+ [Obsolete("Use CreateShader(SKShader) instead.", true)]
+ public static SKImageFilter CreatePaint (SKPaint paint)
+ {
+ _ = paint ?? throw new ArgumentNullException (nameof (paint));
+ return CreateShader(paint.Shader, paint.IsDither, null);
+ }
+
+ [Obsolete("Use CreateShader(SKShader, bool, SKRect) instead.", true)]
+ public static SKImageFilter CreatePaint (SKPaint paint, SKRect cropRect)
+ {
+ _ = paint ?? throw new ArgumentNullException (nameof (paint));
+ return CreateShader(paint.Shader, paint.IsDither, &cropRect);
+ }
+
// CreateShader
public static SKImageFilter CreateShader (SKShader? shader) =>
diff --git a/binding/SkiaSharp/SKMatrix44.cs b/binding/SkiaSharp/SKMatrix44.cs
index dfbe3754df..8c44538d4a 100644
--- a/binding/SkiaSharp/SKMatrix44.cs
+++ b/binding/SkiaSharp/SKMatrix44.cs
@@ -2,6 +2,7 @@
using System;
using System.Numerics;
+using System.Runtime.CompilerServices;
namespace SkiaSharp
{
@@ -348,46 +349,46 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
public SKMatrix Matrix =>
new SKMatrix (
- m00, m01, m03,
- m10, m11, m13,
- m30, m31, m33);
+ m00, m10, m30,
+ m01, m11, m31,
+ m03, m13, m33);
public float this[int row, int column] {
- get => column switch {
- 0 => row switch {
+ get => row switch {
+ 0 => column switch {
0 => m00,
1 => m01,
2 => m02,
3 => m03,
- _ => throw new ArgumentOutOfRangeException (nameof (row))
+ _ => throw new ArgumentOutOfRangeException (nameof (column))
},
- 1 => row switch {
+ 1 => column switch {
0 => m10,
1 => m11,
2 => m12,
3 => m13,
- _ => throw new ArgumentOutOfRangeException (nameof (row))
+ _ => throw new ArgumentOutOfRangeException (nameof (column))
},
- 2 => row switch {
+ 2 => column switch {
0 => m20,
1 => m21,
2 => m22,
3 => m23,
- _ => throw new ArgumentOutOfRangeException (nameof (row))
+ _ => throw new ArgumentOutOfRangeException (nameof (column))
},
- 3 => row switch {
+ 3 => column switch {
0 => m30,
1 => m31,
2 => m32,
3 => m33,
- _ => throw new ArgumentOutOfRangeException (nameof (row))
+ _ => throw new ArgumentOutOfRangeException (nameof (column))
},
- _ => throw new ArgumentOutOfRangeException (nameof (column))
+ _ => throw new ArgumentOutOfRangeException (nameof (row))
};
set {
- switch (column) {
+ switch (row) {
case 0:
- switch (row) {
+ switch (column) {
case 0:
m00 = value;
break;
@@ -401,11 +402,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
m03 = value;
break;
default:
- throw new ArgumentOutOfRangeException (nameof (row));
+ throw new ArgumentOutOfRangeException (nameof (column));
};
break;
case 1:
- switch (row) {
+ switch (column) {
case 0:
m10 = value;
break;
@@ -419,11 +420,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
m13 = value;
break;
default:
- throw new ArgumentOutOfRangeException (nameof (row));
+ throw new ArgumentOutOfRangeException (nameof (column));
};
break;
case 2:
- switch (row) {
+ switch (column) {
case 0:
m20 = value;
break;
@@ -437,11 +438,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
m23 = value;
break;
default:
- throw new ArgumentOutOfRangeException (nameof (row));
+ throw new ArgumentOutOfRangeException (nameof (column));
};
break;
case 3:
- switch (row) {
+ switch (column) {
case 0:
m30 = value;
break;
@@ -455,11 +456,11 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
m33 = value;
break;
default:
- throw new ArgumentOutOfRangeException (nameof (row));
+ throw new ArgumentOutOfRangeException (nameof (column));
};
break;
default:
- throw new ArgumentOutOfRangeException (nameof (column));
+ throw new ArgumentOutOfRangeException (nameof (row));
};
}
}
@@ -468,23 +469,15 @@ public static SKMatrix44 Multiply (SKMatrix44 value1, float value2) =>
public static implicit operator SKMatrix44 (SKMatrix matrix) =>
new SKMatrix44 (
- matrix.ScaleX, matrix.SkewX, 0, matrix.TransX,
- matrix.SkewY, matrix.ScaleY, 0, matrix.TransY,
+ matrix.ScaleX, matrix.SkewY, 0, matrix.Persp0,
+ matrix.SkewX, matrix.ScaleY, 0, matrix.Persp1,
0, 0, 1, 0,
- matrix.Persp0, matrix.Persp1, 0, matrix.Persp2);
+ matrix.TransX, matrix.TransY, 0, matrix.Persp2);
public static implicit operator Matrix4x4 (SKMatrix44 matrix) =>
- new Matrix4x4 (
- matrix.m00, matrix.m10, matrix.m20, matrix.m30,
- matrix.m01, matrix.m11, matrix.m21, matrix.m31,
- matrix.m02, matrix.m12, matrix.m22, matrix.m32,
- matrix.m03, matrix.m13, matrix.m23, matrix.m33);
+ Unsafe.As (ref matrix);
public static implicit operator SKMatrix44 (Matrix4x4 matrix) =>
- new SKMatrix44 (
- matrix.M11, matrix.M21, matrix.M31, matrix.M41,
- matrix.M12, matrix.M22, matrix.M32, matrix.M42,
- matrix.M13, matrix.M23, matrix.M33, matrix.M43,
- matrix.M14, matrix.M24, matrix.M34, matrix.M44);
+ Unsafe.As (ref matrix);
}
}
diff --git a/binding/SkiaSharp/SKObject.cs b/binding/SkiaSharp/SKObject.cs
index aad6bf8cd7..ddaae8b879 100644
--- a/binding/SkiaSharp/SKObject.cs
+++ b/binding/SkiaSharp/SKObject.cs
@@ -44,6 +44,7 @@ static SKObject ()
SKData.EnsureStaticInstanceAreInitialized ();
SKFontManager.EnsureStaticInstanceAreInitialized ();
SKTypeface.EnsureStaticInstanceAreInitialized ();
+ SKBlender.EnsureStaticInstanceAreInitialized ();
}
internal SKObject (IntPtr handle, bool owns)
@@ -195,7 +196,7 @@ internal static T Owned (T owner, SKObject child)
return owner;
}
- // indicate that the chile should not be garbage collected while
+ // indicate that the child should not be garbage collected while
// the owner still lives
internal static T Referenced (T owner, SKObject child)
where T : SKObject
@@ -350,11 +351,19 @@ public static int GetReferenceCount (this ISKReferenceCounted obj)
}
}
+ ///
+ /// This should be implemented on all types that inherit directly or
+ /// indirectly from SkRefCnt or SkRefCntBase
+ ///
internal interface ISKReferenceCounted
{
IntPtr Handle { get; }
}
+ ///
+ /// This should be implemented on all types that inherit directly or
+ /// indirectly from SkNVRefCnt
+ ///
internal interface ISKNonVirtualReferenceCounted : ISKReferenceCounted
{
void ReferenceNative ();
@@ -362,6 +371,12 @@ internal interface ISKNonVirtualReferenceCounted : ISKReferenceCounted
void UnreferenceNative ();
}
+ ///
+ /// This should be implemented on all types that can skip the expensive
+ /// registration in the global dictionary. Typically this would be the case
+ /// if the type os _only_ constructed by the user and not provided as a
+ /// return type for _any_ member.
+ ///
internal interface ISKSkipObjectRegistration
{
}
diff --git a/binding/SkiaSharp/SKPaint.cs b/binding/SkiaSharp/SKPaint.cs
index 09dde1ff23..1e8d1be424 100644
--- a/binding/SkiaSharp/SKPaint.cs
+++ b/binding/SkiaSharp/SKPaint.cs
@@ -203,6 +203,11 @@ public SKBlendMode BlendMode {
set => SkiaApi.sk_paint_set_blendmode (Handle, value);
}
+ public SKBlender Blender {
+ get => SKBlender.GetObject (SkiaApi.sk_paint_get_blender (Handle));
+ set => SkiaApi.sk_paint_set_blender (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
[Obsolete ($"Use {nameof (SKSamplingOptions)} instead.")]
public SKFilterQuality FilterQuality {
get => (SKFilterQuality)SkiaApi.sk_compatpaint_get_filter_quality (Handle);
diff --git a/binding/SkiaSharp/SKPath.cs b/binding/SkiaSharp/SKPath.cs
index d1a0d7f0e1..d4b36fbe8c 100644
--- a/binding/SkiaSharp/SKPath.cs
+++ b/binding/SkiaSharp/SKPath.cs
@@ -181,8 +181,11 @@ public bool Contains (float x, float y) =>
public void Offset (SKPoint offset) =>
Offset (offset.X, offset.Y);
- public void Offset (float dx, float dy) =>
- Transform (SKMatrix.CreateTranslation (dx, dy));
+ public void Offset (float dx, float dy)
+ {
+ var matrix = SKMatrix.CreateTranslation (dx, dy);
+ Transform (in matrix);
+ }
public void MoveTo (SKPoint point) =>
SkiaApi.sk_path_move_to (Handle, point.X, point.Y);
@@ -340,6 +343,14 @@ public void Transform (in SKMatrix matrix, SKPath destination)
SkiaApi.sk_path_transform_to_dest (Handle, m, destination.Handle);
}
+ [Obsolete("Use Transform(in SKMatrix) instead.", true)]
+ public void Transform (SKMatrix matrix) =>
+ Transform (in matrix);
+
+ [Obsolete("Use Transform(in SKMatrix matrix, SKPath destination) instead.", true)]
+ public void Transform (SKMatrix matrix, SKPath destination) =>
+ Transform (in matrix, destination);
+
public void AddPath (SKPath other, float dx, float dy, SKPathAddMode mode = SKPathAddMode.Append)
{
if (other == null)
diff --git a/binding/SkiaSharp/SKRunBuffer.cs b/binding/SkiaSharp/SKRunBuffer.cs
index 8f4916104e..65831136ef 100644
--- a/binding/SkiaSharp/SKRunBuffer.cs
+++ b/binding/SkiaSharp/SKRunBuffer.cs
@@ -1,10 +1,11 @@
#nullable disable
using System;
-using System.ComponentModel;
namespace SkiaSharp
{
+ // Base
+
public unsafe class SKRunBuffer
{
internal readonly SKRunBufferInternal internalBuffer;
@@ -17,103 +18,142 @@ internal SKRunBuffer (SKRunBufferInternal buffer, int size)
public int Size { get; }
- public Span GetGlyphSpan () =>
- new Span (internalBuffer.glyphs, internalBuffer.glyphs == null ? 0 : Size);
+ public Span Glyphs => new (internalBuffer.glyphs, Size);
+
+ public void SetGlyphs (ReadOnlySpan glyphs) => glyphs.CopyTo (Glyphs);
- public void SetGlyphs (ReadOnlySpan glyphs) =>
- glyphs.CopyTo (GetGlyphSpan ());
+ [Obsolete ("Use Glyphs instead.")]
+ public Span GetGlyphSpan () => Glyphs;
}
public sealed unsafe class SKHorizontalRunBuffer : SKRunBuffer
{
- internal SKHorizontalRunBuffer (SKRunBufferInternal buffer, int count)
- : base (buffer, count)
+ internal SKHorizontalRunBuffer (SKRunBufferInternal buffer, int size)
+ : base (buffer, size)
{
}
- public Span GetPositionSpan () =>
- new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+ public Span Positions => new (internalBuffer.pos, Size);
- public void SetPositions (ReadOnlySpan positions) =>
- positions.CopyTo (GetPositionSpan ());
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
+
+ [Obsolete ("Use Positions instead.")]
+ public Span GetPositionSpan () => Positions;
}
public sealed unsafe class SKPositionedRunBuffer : SKRunBuffer
{
- internal SKPositionedRunBuffer (SKRunBufferInternal buffer, int count)
- : base (buffer, count)
+ internal SKPositionedRunBuffer (SKRunBufferInternal buffer, int size)
+ : base (buffer, size)
{
}
- public Span GetPositionSpan () =>
- new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+ public Span Positions => new (internalBuffer.pos, Size);
+
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
- public void SetPositions (ReadOnlySpan positions) =>
- positions.CopyTo (GetPositionSpan ());
+ [Obsolete ("Use Positions instead.")]
+ public Span GetPositionSpan () => Positions;
}
public sealed unsafe class SKRotationScaleRunBuffer : SKRunBuffer
{
- internal SKRotationScaleRunBuffer (SKRunBufferInternal buffer, int count)
- : base (buffer, count)
+ internal SKRotationScaleRunBuffer (SKRunBufferInternal buffer, int size)
+ : base (buffer, size)
{
}
- public Span GetRotationScaleSpan () =>
- new Span (internalBuffer.pos, Size);
+ public Span Positions => new (internalBuffer.pos, Size);
- public void SetRotationScale (ReadOnlySpan positions) =>
- positions.CopyTo (GetRotationScaleSpan ());
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
+
+ [Obsolete ("Use Positions instead.")]
+ public Span GetRotationScaleSpan () => Positions;
+
+ [Obsolete ("Use SetPositions instead.")]
+ public void SetRotationScale (ReadOnlySpan positions) => SetPositions (positions);
}
+ // Text
+
public unsafe class SKTextRunBuffer : SKRunBuffer
{
- internal SKTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
- : base (buffer, count)
+ internal SKTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize)
+ : base (buffer, size)
{
TextSize = textSize;
}
public int TextSize { get; }
- public Span GetTextSpan () =>
- new Span (internalBuffer.utf8text, internalBuffer.utf8text == null ? 0 : TextSize);
+ public Span Text => new (internalBuffer.utf8text, TextSize);
- public Span GetClusterSpan () =>
- new Span (internalBuffer.clusters, internalBuffer.clusters == null ? 0 : Size);
+ public Span Clusters => new (internalBuffer.clusters, Size);
- public void SetText (ReadOnlySpan text) =>
- text.CopyTo (GetTextSpan ());
+ public void SetText (ReadOnlySpan text) => text.CopyTo (Text);
- public void SetClusters (ReadOnlySpan clusters) =>
- clusters.CopyTo (GetClusterSpan ());
+ public void SetClusters (ReadOnlySpan clusters) => clusters.CopyTo (Clusters);
}
public sealed unsafe class SKHorizontalTextRunBuffer : SKTextRunBuffer
{
- internal SKHorizontalTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
- : base (buffer, count, textSize)
+ internal SKHorizontalTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize)
+ : base (buffer, size, textSize)
{
}
- public Span GetPositionSpan () =>
- new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+ public Span Positions => new (internalBuffer.pos, Size);
- public void SetPositions (ReadOnlySpan positions) =>
- positions.CopyTo (GetPositionSpan ());
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
}
public sealed unsafe class SKPositionedTextRunBuffer : SKTextRunBuffer
{
- internal SKPositionedTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
- : base (buffer, count, textSize)
+ internal SKPositionedTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize)
+ : base (buffer, size, textSize)
{
}
- public Span GetPositionSpan () =>
- new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+ public Span Positions => new (internalBuffer.pos, Size);
+
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
+ }
+
+ public sealed unsafe class SKRotationScaleTextRunBuffer : SKTextRunBuffer
+ {
+ internal SKRotationScaleTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize)
+ : base (buffer, size, textSize)
+ {
+ }
+
+ public Span Positions => new (internalBuffer.pos, Size);
+
+ public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions);
+ }
+
+ // Raw / Struct
+
+ public unsafe readonly struct SKRawRunBuffer
+ {
+ internal readonly SKRunBufferInternal buffer;
+ private readonly int size;
+ private readonly int posSize;
+ private readonly int textSize;
+
+ internal SKRawRunBuffer (SKRunBufferInternal buffer, int size, int posSize, int textSize)
+ {
+ this.buffer = buffer;
+ this.size = size;
+ this.posSize = posSize;
+ this.textSize = textSize;
+ }
+
+ public Span Glyphs => new (buffer.glyphs, size);
+
+ public Span Positions => new (buffer.pos, posSize);
+
+ public Span Text => new (buffer.utf8text, textSize);
- public void SetPositions (ReadOnlySpan positions) =>
- positions.CopyTo (GetPositionSpan ());
+ public Span Clusters => new (buffer.clusters, size);
}
}
diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs
index 8487aa8f86..9a26537938 100644
--- a/binding/SkiaSharp/SKRuntimeEffect.cs
+++ b/binding/SkiaSharp/SKRuntimeEffect.cs
@@ -41,6 +41,17 @@ public static SKRuntimeEffect CreateColorFilter (string sksl, out string errors)
return effect;
}
+ public static SKRuntimeEffect CreateBlender (string sksl, out string errors)
+ {
+ using var s = new SKString (sksl);
+ using var errorString = new SKString ();
+ var effect = GetObject (SkiaApi.sk_runtimeeffect_make_for_blender (s.Handle, errorString.Handle));
+ errors = errorString?.ToString ();
+ if (errors?.Length == 0)
+ errors = null;
+ return effect;
+ }
+
// Build*
public static SKRuntimeShaderBuilder BuildShader (string sksl)
@@ -57,6 +68,13 @@ public static SKRuntimeColorFilterBuilder BuildColorFilter (string sksl)
return new SKRuntimeColorFilterBuilder (effect);
}
+ public static SKRuntimeBlenderBuilder BuildBlender (string sksl)
+ {
+ var effect = CreateBlender (sksl, out var errors);
+ ValidateResult (effect, errors);
+ return new SKRuntimeBlenderBuilder (effect);
+ }
+
private static void ValidateResult (SKRuntimeEffect effect, string errors)
{
if (effect is null) {
@@ -148,6 +166,30 @@ private SKColorFilter ToColorFilter (SKData uniforms, SKObject[] children)
}
}
+ // ToBlender
+
+ public SKBlender ToBlender () =>
+ ToBlender ((SKData)null, null);
+
+ public SKBlender ToBlender (SKRuntimeEffectUniforms uniforms) =>
+ ToBlender (uniforms.ToData (), null);
+
+ private SKBlender ToBlender (SKData uniforms) =>
+ ToBlender (uniforms, null);
+
+ public SKBlender ToBlender (SKRuntimeEffectUniforms uniforms, SKRuntimeEffectChildren children) =>
+ ToBlender (uniforms.ToData (), children.ToArray ());
+
+ private SKBlender ToBlender (SKData uniforms, SKObject[] children)
+ {
+ var uniformsHandle = uniforms?.Handle ?? IntPtr.Zero;
+ using var childrenHandles = Utils.RentHandlesArray (children, true);
+
+ fixed (IntPtr* ch = childrenHandles) {
+ return SKBlender.GetObject (SkiaApi.sk_runtimeeffect_make_blender (Handle, uniformsHandle, ch, (IntPtr)childrenHandles.Length));
+ }
+ }
+
//
internal static SKRuntimeEffect GetObject (IntPtr handle) =>
@@ -560,15 +602,24 @@ public SKRuntimeEffectChild (SKColorFilter colorFilter)
value = colorFilter;
}
+ public SKRuntimeEffectChild (SKBlender blender)
+ {
+ value = blender;
+ }
+
public SKObject Value => value;
public SKShader Shader => value as SKShader;
public SKColorFilter ColorFilter => value as SKColorFilter;
+ public SKBlender Blender => value as SKBlender;
+
public static implicit operator SKRuntimeEffectChild (SKShader shader) => new (shader);
public static implicit operator SKRuntimeEffectChild (SKColorFilter colorFilter) => new (colorFilter);
+
+ public static implicit operator SKRuntimeEffectChild (SKBlender blender) => new (blender);
}
public class SKRuntimeEffectBuilderException : ApplicationException
@@ -627,4 +678,15 @@ public SKRuntimeColorFilterBuilder (SKRuntimeEffect effect)
public SKColorFilter Build () =>
Effect.ToColorFilter (Uniforms, Children);
}
+
+ public class SKRuntimeBlenderBuilder : SKRuntimeEffectBuilder
+ {
+ public SKRuntimeBlenderBuilder (SKRuntimeEffect effect)
+ : base (effect)
+ {
+ }
+
+ public SKBlender Build () =>
+ Effect.ToBlender (Uniforms, Children);
+ }
}
diff --git a/binding/SkiaSharp/SKShader.cs b/binding/SkiaSharp/SKShader.cs
index 9216985672..6069b57776 100644
--- a/binding/SkiaSharp/SKShader.cs
+++ b/binding/SkiaSharp/SKShader.cs
@@ -408,6 +408,23 @@ public static SKShader CreateCompose (SKShader shaderA, SKShader shaderB, SKBlen
return GetObject (SkiaApi.sk_shader_new_blend (mode, shaderA.Handle, shaderB.Handle));
}
+ // CreateBlend
+
+ public static SKShader CreateBlend (SKBlendMode mode, SKShader shaderA, SKShader shaderB)
+ {
+ _ = shaderA ?? throw new ArgumentNullException (nameof (shaderA));
+ _ = shaderB ?? throw new ArgumentNullException (nameof (shaderB));
+ return GetObject (SkiaApi.sk_shader_new_blend (mode, shaderA.Handle, shaderB.Handle));
+ }
+
+ public static SKShader CreateBlend (SKBlender blender, SKShader shaderA, SKShader shaderB)
+ {
+ _ = shaderA ?? throw new ArgumentNullException (nameof (shaderA));
+ _ = shaderB ?? throw new ArgumentNullException (nameof (shaderB));
+ _ = blender ?? throw new ArgumentNullException (nameof (blender));
+ return GetObject (SkiaApi.sk_shader_new_blender (blender.Handle, shaderA.Handle, shaderB.Handle));
+ }
+
// CreateColorFilter
public static SKShader CreateColorFilter (SKShader shader, SKColorFilter filter)
diff --git a/binding/SkiaSharp/SKTextBlob.cs b/binding/SkiaSharp/SKTextBlob.cs
index 704b3e95b8..10193d25a0 100644
--- a/binding/SkiaSharp/SKTextBlob.cs
+++ b/binding/SkiaSharp/SKTextBlob.cs
@@ -1,7 +1,4 @@
-#nullable disable
-
-using System;
-using System.ComponentModel;
+using System;
namespace SkiaSharp
{
@@ -31,27 +28,27 @@ public SKRect Bounds {
// Create
- public static SKTextBlob Create (string text, SKFont font, SKPoint origin = default) =>
+ public static SKTextBlob? Create (string text, SKFont font, SKPoint origin = default) =>
Create (text.AsSpan (), font, origin);
- public static SKTextBlob Create (ReadOnlySpan text, SKFont font, SKPoint origin = default)
+ public static SKTextBlob? Create (ReadOnlySpan text, SKFont font, SKPoint origin = default)
{
fixed (void* t = text) {
return Create (t, text.Length * 2, SKTextEncoding.Utf16, font, origin);
}
}
- public static SKTextBlob Create (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin = default) =>
+ public static SKTextBlob? Create (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin = default) =>
Create (text.AsReadOnlySpan (length), encoding, font, origin);
- public static SKTextBlob Create (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPoint origin = default)
+ public static SKTextBlob? Create (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPoint origin = default)
{
fixed (void* t = text) {
return Create (t, text.Length, encoding, font, origin);
}
}
- internal static SKTextBlob Create (void* text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin)
+ internal static SKTextBlob? Create (void* text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -61,35 +58,35 @@ internal static SKTextBlob Create (void* text, int length, SKTextEncoding encodi
return null;
using var builder = new SKTextBlobBuilder ();
- var buffer = builder.AllocatePositionedRun (font, count);
- font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ());
- font.GetGlyphPositions (buffer.GetGlyphSpan (), buffer.GetPositionSpan (), origin);
+ var buffer = builder.AllocateRawPositionedRun (font, count);
+ font.GetGlyphs (text, length, encoding, buffer.Glyphs);
+ font.GetGlyphPositions (buffer.Glyphs, buffer.Positions, origin);
return builder.Build ();
}
// CreateHorizontal
- public static SKTextBlob CreateHorizontal (string text, SKFont font, ReadOnlySpan positions, float y) =>
+ public static SKTextBlob? CreateHorizontal (string text, SKFont font, ReadOnlySpan positions, float y) =>
CreateHorizontal (text.AsSpan (), font, positions, y);
- public static SKTextBlob CreateHorizontal (ReadOnlySpan text, SKFont font, ReadOnlySpan positions, float y)
+ public static SKTextBlob? CreateHorizontal (ReadOnlySpan text, SKFont font, ReadOnlySpan positions, float y)
{
fixed (void* t = text) {
return CreateHorizontal (t, text.Length * 2, SKTextEncoding.Utf16, font, positions, y);
}
}
- public static SKTextBlob CreateHorizontal (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) =>
+ public static SKTextBlob? CreateHorizontal (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) =>
CreateHorizontal (text.AsReadOnlySpan (length), encoding, font, positions, y);
- public static SKTextBlob CreateHorizontal (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y)
+ public static SKTextBlob? CreateHorizontal (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y)
{
fixed (void* t = text) {
return CreateHorizontal (t, text.Length, encoding, font, positions, y);
}
}
- internal static SKTextBlob CreateHorizontal (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y)
+ internal static SKTextBlob? CreateHorizontal (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -99,35 +96,35 @@ internal static SKTextBlob CreateHorizontal (void* text, int length, SKTextEncod
return null;
using var builder = new SKTextBlobBuilder ();
- var buffer = builder.AllocateHorizontalRun (font, count, y);
- font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetPositionSpan ());
+ var buffer = builder.AllocateRawHorizontalRun (font, count, y);
+ font.GetGlyphs (text, length, encoding, buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
return builder.Build ();
}
// CreatePositioned
- public static SKTextBlob CreatePositioned (string text, SKFont font, ReadOnlySpan positions) =>
+ public static SKTextBlob? CreatePositioned (string text, SKFont font, ReadOnlySpan positions) =>
CreatePositioned (text.AsSpan (), font, positions);
- public static SKTextBlob CreatePositioned (ReadOnlySpan text, SKFont font, ReadOnlySpan positions)
+ public static SKTextBlob? CreatePositioned (ReadOnlySpan text, SKFont font, ReadOnlySpan positions)
{
fixed (void* t = text) {
return CreatePositioned (t, text.Length * 2, SKTextEncoding.Utf16, font, positions);
}
}
- public static SKTextBlob CreatePositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) =>
+ public static SKTextBlob? CreatePositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) =>
CreatePositioned (text.AsReadOnlySpan (length), encoding, font, positions);
- public static SKTextBlob CreatePositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
+ public static SKTextBlob? CreatePositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
{
fixed (void* t = text) {
return CreatePositioned (t, text.Length, encoding, font, positions);
}
}
- internal static SKTextBlob CreatePositioned (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
+ internal static SKTextBlob? CreatePositioned (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -137,35 +134,35 @@ internal static SKTextBlob CreatePositioned (void* text, int length, SKTextEncod
return null;
using var builder = new SKTextBlobBuilder ();
- var buffer = builder.AllocatePositionedRun (font, count);
- font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetPositionSpan ());
+ var buffer = builder.AllocateRawPositionedRun (font, count);
+ font.GetGlyphs (text, length, encoding, buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
return builder.Build ();
}
// CreateRotationScale
- public static SKTextBlob CreateRotationScale (string text, SKFont font, ReadOnlySpan positions) =>
+ public static SKTextBlob? CreateRotationScale (string text, SKFont font, ReadOnlySpan positions) =>
CreateRotationScale (text.AsSpan (), font, positions);
- public static SKTextBlob CreateRotationScale (ReadOnlySpan text, SKFont font, ReadOnlySpan positions)
+ public static SKTextBlob? CreateRotationScale (ReadOnlySpan text, SKFont font, ReadOnlySpan positions)
{
fixed (void* t = text) {
return CreateRotationScale (t, text.Length * 2, SKTextEncoding.Utf16, font, positions);
}
}
- public static SKTextBlob CreateRotationScale (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) =>
+ public static SKTextBlob? CreateRotationScale (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) =>
CreateRotationScale (text.AsReadOnlySpan (length), encoding, font, positions);
- public static SKTextBlob CreateRotationScale (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
+ public static SKTextBlob? CreateRotationScale (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
{
fixed (void* t = text) {
return CreateRotationScale (t, text.Length, encoding, font, positions);
}
}
- internal static SKTextBlob CreateRotationScale (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
+ internal static SKTextBlob? CreateRotationScale (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -176,34 +173,34 @@ internal static SKTextBlob CreateRotationScale (void* text, int length, SKTextEn
using var builder = new SKTextBlobBuilder ();
var buffer = builder.AllocateRotationScaleRun (font, count);
- font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetRotationScaleSpan ());
+ font.GetGlyphs (text, length, encoding, buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
return builder.Build ();
}
// CreatePathPositioned
- public static SKTextBlob CreatePathPositioned (string text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) =>
+ public static SKTextBlob? CreatePathPositioned (string text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) =>
CreatePathPositioned (text.AsSpan (), font, path, textAlign, origin);
- public static SKTextBlob CreatePathPositioned (ReadOnlySpan text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
+ public static SKTextBlob? CreatePathPositioned (ReadOnlySpan text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
{
fixed (void* t = text) {
return CreatePathPositioned (t, text.Length * 2, SKTextEncoding.Utf16, font, path, textAlign, origin);
}
}
- public static SKTextBlob CreatePathPositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) =>
+ public static SKTextBlob? CreatePathPositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) =>
CreatePathPositioned (text.AsReadOnlySpan (length), encoding, font, path, textAlign, origin);
- public static SKTextBlob CreatePathPositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
+ public static SKTextBlob? CreatePathPositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
{
fixed (void* t = text) {
return CreatePathPositioned (t, text.Length, encoding, font, path, textAlign, origin);
}
}
- internal static SKTextBlob CreatePathPositioned (void* text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
+ internal static SKTextBlob? CreatePathPositioned (void* text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -228,7 +225,7 @@ internal static SKTextBlob CreatePathPositioned (void* text, int length, SKTextE
// GetIntercepts
- public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint paint = null)
+ public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint? paint = null)
{
var n = CountIntercepts (upperBounds, lowerBounds, paint);
var intervals = new float[n];
@@ -236,7 +233,7 @@ public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint pain
return intervals;
}
- public void GetIntercepts (float upperBounds, float lowerBounds, Span intervals, SKPaint paint = null)
+ public void GetIntercepts (float upperBounds, float lowerBounds, Span intervals, SKPaint? paint = null)
{
var bounds = stackalloc float[2];
bounds[0] = upperBounds;
@@ -248,7 +245,7 @@ public void GetIntercepts (float upperBounds, float lowerBounds, Span int
// CountIntercepts
- public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint paint = null)
+ public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint? paint = null)
{
var bounds = stackalloc float[2];
bounds[0] = upperBounds;
@@ -258,7 +255,7 @@ public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint paint
//
- internal static SKTextBlob GetObject (IntPtr handle) =>
+ internal static SKTextBlob? GetObject (IntPtr handle) =>
handle == IntPtr.Zero ? null : new SKTextBlob (handle, true);
}
@@ -282,7 +279,7 @@ protected override void DisposeNative () =>
// Build
- public SKTextBlob Build ()
+ public SKTextBlob? Build ()
{
var blob = SKTextBlob.GetObject (SkiaApi.sk_textblob_builder_make (Handle));
GC.KeepAlive (this);
@@ -293,48 +290,36 @@ public SKTextBlob Build ()
public void AddRun (ReadOnlySpan glyphs, SKFont font, SKPoint origin = default)
{
- if (font == null)
- throw new ArgumentNullException (nameof (font));
-
- var buffer = AllocatePositionedRun (font, glyphs.Length);
- glyphs.CopyTo (buffer.GetGlyphSpan ());
- font.GetGlyphPositions (buffer.GetGlyphSpan (), buffer.GetPositionSpan (), origin);
+ var buffer = AllocateRawPositionedRun (font, glyphs.Length);
+ glyphs.CopyTo (buffer.Glyphs);
+ font.GetGlyphPositions (buffer.Glyphs, buffer.Positions, origin);
}
// AddHorizontalRun
public void AddHorizontalRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions, float y)
{
- if (font == null)
- throw new ArgumentNullException (nameof (font));
-
- var buffer = AllocateHorizontalRun (font, glyphs.Length, y);
- glyphs.CopyTo (buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetPositionSpan ());
+ var buffer = AllocateRawHorizontalRun (font, glyphs.Length, y);
+ glyphs.CopyTo (buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
}
// AddPositionedRun
public void AddPositionedRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions)
{
- if (font == null)
- throw new ArgumentNullException (nameof (font));
-
- var buffer = AllocatePositionedRun (font, glyphs.Length);
- glyphs.CopyTo (buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetPositionSpan ());
+ var buffer = AllocateRawPositionedRun (font, glyphs.Length);
+ glyphs.CopyTo (buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
}
// AddRotationScaleRun
public void AddRotationScaleRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions)
{
- if (font == null)
- throw new ArgumentNullException (nameof (font));
-
- var buffer = AllocateRotationScaleRun (font, glyphs.Length);
- glyphs.CopyTo (buffer.GetGlyphSpan ());
- positions.CopyTo (buffer.GetRotationScaleSpan ());
+ var buffer = AllocateRawRotationScaleRun (font, glyphs.Length);
+ glyphs.CopyTo (buffer.Glyphs);
+ positions.CopyTo (buffer.Positions);
}
// AddPathPositionedRun
@@ -390,9 +375,17 @@ public void AddPathPositionedRun (ReadOnlySpan glyphs, SKFont font, Read
AddRotationScaleRun (glyphSubset, font, positions);
}
- // AllocateRun
+ // Allocate*
+
+ // Allocate*Run
public SKRunBuffer AllocateRun (SKFont font, int count, float x, float y, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawRun (font, count, x, y, bounds);
+ return new SKRunBuffer (buffer.buffer, count);
+ }
+
+ public SKRawRunBuffer AllocateRawRun (SKFont font, int count, float x, float y, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -403,10 +396,16 @@ public SKRunBuffer AllocateRun (SKFont font, int count, float x, float y, SKRect
else
SkiaApi.sk_textblob_builder_alloc_run (Handle, font.Handle, count, x, y, null, &runbuffer);
- return new SKRunBuffer (runbuffer, count);
+ return new SKRawRunBuffer (runbuffer, count, 0, 0);
}
public SKTextRunBuffer AllocateTextRun (SKFont font, int count, float x, float y, int textByteCount, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawTextRun (font, count, x, y, textByteCount, bounds);
+ return new SKTextRunBuffer (buffer.buffer, count, textByteCount);
+ }
+
+ public SKRawRunBuffer AllocateRawTextRun (SKFont font, int count, float x, float y, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -417,12 +416,18 @@ public SKTextRunBuffer AllocateTextRun (SKFont font, int count, float x, float y
else
SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, null, &runbuffer);
- return new SKTextRunBuffer (runbuffer, count, textByteCount);
+ return new SKRawRunBuffer (runbuffer, count, 0, textByteCount);
}
- // AllocateHorizontalRun
+ // Allocate*HorizontalRun
public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, float y, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawHorizontalRun (font, count, y, bounds);
+ return new SKHorizontalRunBuffer (buffer.buffer, count);
+ }
+
+ public SKRawRunBuffer AllocateRawHorizontalRun (SKFont font, int count, float y, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -433,10 +438,16 @@ public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, floa
else
SkiaApi.sk_textblob_builder_alloc_run_pos_h (Handle, font.Handle, count, y, null, &runbuffer);
- return new SKHorizontalRunBuffer (runbuffer, count);
+ return new SKRawRunBuffer (runbuffer, count, count, 0);
}
public SKHorizontalTextRunBuffer AllocateHorizontalTextRun (SKFont font, int count, float y, int textByteCount, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawHorizontalTextRun (font, count, y, textByteCount, bounds);
+ return new SKHorizontalTextRunBuffer (buffer.buffer, count, textByteCount);
+ }
+
+ public SKRawRunBuffer AllocateRawHorizontalTextRun (SKFont font, int count, float y, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -447,12 +458,19 @@ public SKHorizontalTextRunBuffer AllocateHorizontalTextRun (SKFont font, int cou
else
SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, null, &runbuffer);
- return new SKHorizontalTextRunBuffer (runbuffer, count, textByteCount);
+ return new SKRawRunBuffer (runbuffer, count, count, textByteCount);
+
}
// AllocatePositionedRun
public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawPositionedRun (font, count, bounds);
+ return new SKPositionedRunBuffer (buffer.buffer, count);
+ }
+
+ public SKRawRunBuffer AllocateRawPositionedRun (SKFont font, int count, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -463,10 +481,16 @@ public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRe
else
SkiaApi.sk_textblob_builder_alloc_run_pos (Handle, font.Handle, count, null, &runbuffer);
- return new SKPositionedRunBuffer (runbuffer, count);
+ return new SKRawRunBuffer (runbuffer, count, count, 0);
}
public SKPositionedTextRunBuffer AllocatePositionedTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawPositionedTextRun (font, count, textByteCount, bounds);
+ return new SKPositionedTextRunBuffer (buffer.buffer, count, textByteCount);
+ }
+
+ public SKRawRunBuffer AllocateRawPositionedTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -477,12 +501,18 @@ public SKPositionedTextRunBuffer AllocatePositionedTextRun (SKFont font, int cou
else
SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, null, &runbuffer);
- return new SKPositionedTextRunBuffer (runbuffer, count, textByteCount);
+ return new SKRawRunBuffer (runbuffer, count, count, textByteCount);
}
// AllocateRotationScaleRun
public SKRotationScaleRunBuffer AllocateRotationScaleRun (SKFont font, int count, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawRotationScaleRun (font, count, bounds);
+ return new SKRotationScaleRunBuffer (buffer.buffer, count);
+ }
+
+ public SKRawRunBuffer AllocateRawRotationScaleRun (SKFont font, int count, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -493,10 +523,16 @@ public SKRotationScaleRunBuffer AllocateRotationScaleRun (SKFont font, int count
else
SkiaApi.sk_textblob_builder_alloc_run_rsxform (Handle, font.Handle, count, null, &runbuffer);
- return new SKRotationScaleRunBuffer (runbuffer, count);
+ return new SKRawRunBuffer (runbuffer, count, count, 0);
+ }
+
+ public SKRotationScaleTextRunBuffer AllocateRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
+ {
+ var buffer = AllocateRawRotationScaleTextRun (font, count, textByteCount, bounds);
+ return new SKRotationScaleTextRunBuffer (buffer.buffer, count, textByteCount);
}
- public SKRotationScaleRunBuffer AllocateRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
+ public SKRawRunBuffer AllocateRawRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));
@@ -507,7 +543,7 @@ public SKRotationScaleRunBuffer AllocateRotationScaleTextRun (SKFont font, int c
else
SkiaApi.sk_textblob_builder_alloc_run_text_rsxform (Handle, font.Handle, count, textByteCount, null, &runbuffer);
- return new SKRotationScaleRunBuffer (runbuffer, count);
+ return new SKRawRunBuffer (runbuffer, count, count, textByteCount);
}
}
}
diff --git a/binding/SkiaSharp/SKTypeface.cs b/binding/SkiaSharp/SKTypeface.cs
index 3455c8ec29..f9ea664166 100644
--- a/binding/SkiaSharp/SKTypeface.cs
+++ b/binding/SkiaSharp/SKTypeface.cs
@@ -14,6 +14,11 @@ public unsafe class SKTypeface : SKObject, ISKReferenceCounted
static SKTypeface ()
{
+ // TODO: This is not the best way to do this as it will create a lot of objects that
+ // might not be needed, but it is the only way to ensure that the static
+ // instances are created before any access is made to them.
+ // See more info: SKObject.EnsureStaticInstanceAreInitialized()
+
defaultTypeface = new SKTypefaceStatic (SkiaApi.sk_typeface_ref_default ());
}
diff --git a/binding/SkiaSharp/SkiaApi.generated.cs b/binding/SkiaSharp/SkiaApi.generated.cs
index 662eb8cb8c..3dd311d4dc 100644
--- a/binding/SkiaSharp/SkiaApi.generated.cs
+++ b/binding/SkiaSharp/SkiaApi.generated.cs
@@ -17,6 +17,7 @@
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
+using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;
@@ -84,6 +85,10 @@
using skottie_marker_observer_t = System.IntPtr;
using skottie_property_observer_t = System.IntPtr;
using skottie_resource_provider_t = System.IntPtr;
+using skresources_external_track_asset_t = System.IntPtr;
+using skresources_image_asset_t = System.IntPtr;
+using skresources_multi_frame_image_asset_t = System.IntPtr;
+using skresources_resource_provider_t = System.IntPtr;
using sksg_invalidation_controller_t = System.IntPtr;
using vk_device_t = System.IntPtr;
using vk_instance_t = System.IntPtr;
@@ -1410,6 +1415,66 @@ internal static bool sk_bitmap_try_alloc_pixels_with_flags (sk_bitmap_t cbitmap,
#endregion
+ #region sk_blender.h
+
+ // sk_blender_t* sk_blender_new_arithmetic(float k1, float k2, float k3, float k4, bool enforcePremul)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul);
+ }
+ private static Delegates.sk_blender_new_arithmetic sk_blender_new_arithmetic_delegate;
+ internal static sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul) =>
+ (sk_blender_new_arithmetic_delegate ??= GetSymbol ("sk_blender_new_arithmetic")).Invoke (k1, k2, k3, k4, enforcePremul);
+ #endif
+
+ // sk_blender_t* sk_blender_new_mode(sk_blendmode_t mode)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_blender_t sk_blender_new_mode (SKBlendMode mode);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_blender_t sk_blender_new_mode (SKBlendMode mode);
+ }
+ private static Delegates.sk_blender_new_mode sk_blender_new_mode_delegate;
+ internal static sk_blender_t sk_blender_new_mode (SKBlendMode mode) =>
+ (sk_blender_new_mode_delegate ??= GetSymbol ("sk_blender_new_mode")).Invoke (mode);
+ #endif
+
+ // void sk_blender_ref(sk_blender_t* blender)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_blender_ref (sk_blender_t blender);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void sk_blender_ref (sk_blender_t blender);
+ }
+ private static Delegates.sk_blender_ref sk_blender_ref_delegate;
+ internal static void sk_blender_ref (sk_blender_t blender) =>
+ (sk_blender_ref_delegate ??= GetSymbol ("sk_blender_ref")).Invoke (blender);
+ #endif
+
+ // void sk_blender_unref(sk_blender_t* blender)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_blender_unref (sk_blender_t blender);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void sk_blender_unref (sk_blender_t blender);
+ }
+ private static Delegates.sk_blender_unref sk_blender_unref_delegate;
+ internal static void sk_blender_unref (sk_blender_t blender) =>
+ (sk_blender_unref_delegate ??= GetSymbol ("sk_blender_unref")).Invoke (blender);
+ #endif
+
+ #endregion
+
#region sk_canvas.h
// void sk_canvas_clear(sk_canvas_t* ccanvas, sk_color_t color)
@@ -4960,6 +5025,20 @@ internal static sk_shader_t sk_image_make_shader (sk_image_t image, SKShaderTile
(sk_image_make_shader_delegate ??= GetSymbol ("sk_image_make_shader")).Invoke (image, tileX, tileY, sampling, cmatrix);
#endif
+ // sk_shader_t* sk_image_make_raw_shader(const sk_image_t* image, sk_shader_tilemode_t tileX, sk_shader_tilemode_t tileY, const sk_sampling_options_t* sampling, const sk_matrix_t* cmatrix)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_image_make_raw_shader (sk_image_t image, SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions* sampling, SKMatrix* cmatrix);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_shader_t sk_image_make_raw_shader (sk_image_t image, SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions* sampling, SKMatrix* cmatrix);
+ }
+ private static Delegates.sk_image_make_raw_shader sk_image_make_raw_shader_delegate;
+ internal static sk_shader_t sk_image_make_raw_shader (sk_image_t image, SKShaderTileMode tileX, SKShaderTileMode tileY, SKSamplingOptions* sampling, SKMatrix* cmatrix) =>
+ (sk_image_make_raw_shader_delegate ??= GetSymbol ("sk_image_make_raw_shader")).Invoke (image, tileX, tileY, sampling, cmatrix);
+ #endif
+
// sk_image_t* sk_image_make_subset(const sk_image_t* cimage, gr_direct_context_t* context, const sk_irect_t* subset)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -5308,6 +5387,20 @@ internal static sk_imagefilter_t sk_imagefilter_new_blend (SKBlendMode mode, sk_
(sk_imagefilter_new_blend_delegate ??= GetSymbol ("sk_imagefilter_new_blend")).Invoke (mode, background, foreground, cropRect);
#endif
+ // sk_imagefilter_t* sk_imagefilter_new_blender(sk_blender_t* blender, const sk_imagefilter_t* background, const sk_imagefilter_t* foreground, const sk_rect_t* cropRect)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect);
+ }
+ private static Delegates.sk_imagefilter_new_blender sk_imagefilter_new_blender_delegate;
+ internal static sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect) =>
+ (sk_imagefilter_new_blender_delegate ??= GetSymbol ("sk_imagefilter_new_blender")).Invoke (blender, background, foreground, cropRect);
+ #endif
+
// sk_imagefilter_t* sk_imagefilter_new_blur(float sigmaX, float sigmaY, sk_shader_tilemode_t tileMode, const sk_imagefilter_t* input, const sk_rect_t* cropRect)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -5688,6 +5781,24 @@ internal static void sk_imagefilter_unref (sk_imagefilter_t cfilter) =>
#endregion
+ #region sk_linker.h
+
+ // void sk_linker_keep_alive()
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_linker_keep_alive ();
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void sk_linker_keep_alive ();
+ }
+ private static Delegates.sk_linker_keep_alive sk_linker_keep_alive_delegate;
+ internal static void sk_linker_keep_alive () =>
+ (sk_linker_keep_alive_delegate ??= GetSymbol ("sk_linker_keep_alive")).Invoke ();
+ #endif
+
+ #endregion
+
#region sk_maskfilter.h
// sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma)
@@ -5980,6 +6091,20 @@ internal static void sk_paint_delete (sk_paint_t param0) =>
(sk_paint_delete_delegate ??= GetSymbol ("sk_paint_delete")).Invoke (param0);
#endif
+ // sk_blender_t* sk_paint_get_blender(sk_paint_t* cpaint)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_blender_t sk_paint_get_blender (sk_paint_t cpaint);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_blender_t sk_paint_get_blender (sk_paint_t cpaint);
+ }
+ private static Delegates.sk_paint_get_blender sk_paint_get_blender_delegate;
+ internal static sk_blender_t sk_paint_get_blender (sk_paint_t cpaint) =>
+ (sk_paint_get_blender_delegate ??= GetSymbol ("sk_paint_get_blender")).Invoke (cpaint);
+ #endif
+
// sk_blendmode_t sk_paint_get_blendmode(sk_paint_t*)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -6252,6 +6377,20 @@ internal static void sk_paint_set_antialias (sk_paint_t param0, [MarshalAs (Unma
(sk_paint_set_antialias_delegate ??= GetSymbol ("sk_paint_set_antialias")).Invoke (param0, param1);
#endif
+ // void sk_paint_set_blender(sk_paint_t* paint, sk_blender_t* blender)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender);
+ }
+ private static Delegates.sk_paint_set_blender sk_paint_set_blender_delegate;
+ internal static void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender) =>
+ (sk_paint_set_blender_delegate ??= GetSymbol ("sk_paint_set_blender")).Invoke (paint, blender);
+ #endif
+
// void sk_paint_set_blendmode(sk_paint_t*, sk_blendmode_t)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -9438,6 +9577,20 @@ private partial class Delegates {
(sk_runtimeeffect_get_uniforms_size_delegate ??= GetSymbol ("sk_runtimeeffect_get_uniforms_size")).Invoke (effect);
#endif
+ // sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount);
+ }
+ private static Delegates.sk_runtimeeffect_make_blender sk_runtimeeffect_make_blender_delegate;
+ internal static sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount) =>
+ (sk_runtimeeffect_make_blender_delegate ??= GetSymbol ("sk_runtimeeffect_make_blender")).Invoke (effect, uniforms, children, childCount);
+ #endif
+
// sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -9452,6 +9605,20 @@ internal static sk_colorfilter_t sk_runtimeeffect_make_color_filter (sk_runtimee
(sk_runtimeeffect_make_color_filter_delegate ??= GetSymbol ("sk_runtimeeffect_make_color_filter")).Invoke (effect, uniforms, children, childCount);
#endif
+ // sk_runtimeeffect_t* sk_runtimeeffect_make_for_blender(sk_string_t* sksl, sk_string_t* error)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error);
+ }
+ private static Delegates.sk_runtimeeffect_make_for_blender sk_runtimeeffect_make_for_blender_delegate;
+ internal static sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error) =>
+ (sk_runtimeeffect_make_for_blender_delegate ??= GetSymbol ("sk_runtimeeffect_make_for_blender")).Invoke (sksl, error);
+ #endif
+
// sk_runtimeeffect_t* sk_runtimeeffect_make_for_color_filter(sk_string_t* sksl, sk_string_t* error)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@@ -9526,6 +9693,20 @@ internal static sk_shader_t sk_shader_new_blend (SKBlendMode mode, sk_shader_t d
(sk_shader_new_blend_delegate ??= GetSymbol ("sk_shader_new_blend")).Invoke (mode, dst, src);
#endif
+ // sk_shader_t* sk_shader_new_blender(sk_blender_t* blender, const sk_shader_t* dst, const sk_shader_t* src)
+ #if !USE_DELEGATES
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src);
+ #else
+ private partial class Delegates {
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src);
+ }
+ private static Delegates.sk_shader_new_blender sk_shader_new_blender_delegate;
+ internal static sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src) =>
+ (sk_shader_new_blender_delegate ??= GetSymbol ("sk_shader_new_blender")).Invoke (blender, dst, src);
+ #endif
+
// sk_shader_t* sk_shader_new_color(sk_color_t color)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
diff --git a/binding/SkiaSharp/SkiaSharp.csproj b/binding/SkiaSharp/SkiaSharp.csproj
index 4f0937b0b8..eb53cfa375 100644
--- a/binding/SkiaSharp/SkiaSharp.csproj
+++ b/binding/SkiaSharp/SkiaSharp.csproj
@@ -5,6 +5,7 @@
SkiaSharp
SkiaSharp
enable
+ true
$(DefineConstants);USE_DELEGATES
diff --git a/binding/libSkiaSharp.Resources.json b/binding/libSkiaSharp.Resources.json
new file mode 100644
index 0000000000..ed53436df7
--- /dev/null
+++ b/binding/libSkiaSharp.Resources.json
@@ -0,0 +1,86 @@
+// configuration for the libSkiaSharp binary
+{
+ "dllName": "SKIA",
+ "namespace": "SkiaSharp",
+ "namespaces": {
+ "sk_": {
+ "prefix": "SK",
+ "exclude": true
+ },
+ "gr_": {
+ "exclude": true
+ },
+ "vk_": {
+ "exclude": true
+ },
+ "sksg_": {
+ "exclude": true
+ },
+ "skottie_": {
+ "exclude": true
+ },
+ "skresources_": {
+ "cs": "Resources",
+ "prefix": ""
+ }
+ },
+ "className": "ResourcesApi",
+ "includeDirs": [
+ "."
+ ],
+ "headers": {
+ "include/c": [ "sk_*", "gr_*", "skottie*", "sksg_*", "skresources_*" ],
+ "include/xamarin": [ "sk_*" ]
+ },
+ "source": {
+ "src/c": [ "sk_*", "gr_*", "skottie*", "sksg_*" ],
+ "src/xamarin": [ "sk_*" ]
+ },
+ "mappings": {
+ "types": {
+ "skottie_animation_builder_flags_t": {
+ "flags": true
+ }
+ },
+ "functions": {
+ "skottie_animation_builder_make_from_string": {
+ "parameters": {
+ "0": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "1": "int"
+
+ }
+ },
+ "skottie_animation_builder_make_from_file": {
+ "parameters": {
+ "0": "[MarshalAs (UnmanagedType.LPStr)] String"
+ }
+ },
+ "skresources_resource_provider_load": {
+ "parameters": {
+ "1": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "2": "[MarshalAs (UnmanagedType.LPStr)] String"
+ }
+ },
+ "skresources_resource_provider_load_audio_asset": {
+ "parameters": {
+ "1": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "2": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "3": "[MarshalAs (UnmanagedType.LPStr)] String"
+ }
+ },
+ "skresources_resource_provider_load_image_asset": {
+ "parameters": {
+ "1": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "2": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "3": "[MarshalAs (UnmanagedType.LPStr)] String"
+ }
+ },
+ "skresources_resource_provider_load_typeface": {
+ "parameters": {
+ "1": "[MarshalAs (UnmanagedType.LPStr)] String",
+ "2": "[MarshalAs (UnmanagedType.LPStr)] String"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/binding/libSkiaSharp.SceneGraph.json b/binding/libSkiaSharp.SceneGraph.json
index f90dc8e63d..0b432a4d72 100644
--- a/binding/libSkiaSharp.SceneGraph.json
+++ b/binding/libSkiaSharp.SceneGraph.json
@@ -19,6 +19,9 @@
},
"skottie_": {
"exclude": true
+ },
+ "skresources_": {
+ "exclude": true
}
},
"className": "SceneGraphApi",
diff --git a/binding/libSkiaSharp.Skottie.json b/binding/libSkiaSharp.Skottie.json
index e887c28e65..caceca9fb8 100644
--- a/binding/libSkiaSharp.Skottie.json
+++ b/binding/libSkiaSharp.Skottie.json
@@ -19,6 +19,9 @@
"skottie_": {
"cs": "Skottie",
"prefix": ""
+ },
+ "skresources_": {
+ "exclude": true
}
},
"className": "SkottieApi",
@@ -35,6 +38,10 @@
},
"mappings": {
"types": {
+ "skottie_animation_builder_stats_t": {
+ "readonly": true,
+ "properties": false
+ },
"skottie_animation_renderflags_t": {
"cs": "AnimationRenderFlags",
"flags": true
diff --git a/binding/libSkiaSharp.json b/binding/libSkiaSharp.json
index 2e872b0b28..a67a69969c 100644
--- a/binding/libSkiaSharp.json
+++ b/binding/libSkiaSharp.json
@@ -17,6 +17,9 @@
},
"skottie_": {
"exclude": true
+ },
+ "skresources_": {
+ "exclude": true
}
},
"className": "SkiaApi",
diff --git a/build.cake b/build.cake
index 2812886d6d..ba206f5f67 100644
--- a/build.cake
+++ b/build.cake
@@ -101,6 +101,7 @@ var TRACKED_NUGETS = new Dictionary {
{ "SkiaSharp.NativeAssets.Tizen", new Version (1, 60, 0) },
{ "SkiaSharp.NativeAssets.tvOS", new Version (1, 60, 0) },
{ "SkiaSharp.NativeAssets.Win32", new Version (1, 60, 0) },
+ { "SkiaSharp.NativeAssets.WinUI", new Version (1, 60, 0) },
{ "SkiaSharp.Views", new Version (1, 60, 0) },
{ "SkiaSharp.Views.Desktop.Common", new Version (1, 60, 0) },
{ "SkiaSharp.Views.Gtk3", new Version (1, 60, 0) },
@@ -124,6 +125,7 @@ var TRACKED_NUGETS = new Dictionary {
{ "SkiaSharp.HarfBuzz", new Version (1, 60, 0) },
{ "SkiaSharp.Skottie", new Version (1, 60, 0) },
{ "SkiaSharp.SceneGraph", new Version (1, 60, 0) },
+ { "SkiaSharp.Resources", new Version (1, 60, 0) },
{ "SkiaSharp.Vulkan.SharpVk", new Version (1, 60, 0) },
};
diff --git a/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.breaking.md b/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.breaking.md
new file mode 100644
index 0000000000..7ea6364fcb
--- /dev/null
+++ b/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.breaking.md
@@ -0,0 +1,29 @@
+# API diff: SkiaSharp.Views.Maui.Controls.dll
+
+## SkiaSharp.Views.Maui.Controls.dll
+
+> Assembly Version Changed: 3.0.0.0 vs 2.88.0.0
+
+### Namespace SkiaSharp.Views.Maui.Controls
+
+#### Type Changed: SkiaSharp.Views.Maui.Controls.SKCanvasView
+
+Removed interface:
+
+```csharp
+ISKCanvasViewController
+```
+
+
+#### Type Changed: SkiaSharp.Views.Maui.Controls.SKGLView
+
+Removed interface:
+
+```csharp
+ISKGLViewController
+```
+
+
+#### Removed Type SkiaSharp.Views.Maui.Controls.ISKCanvasViewController
+#### Removed Type SkiaSharp.Views.Maui.Controls.ISKGLViewController
+
diff --git a/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.md b/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.md
index a650e725a6..99d1553c0f 100644
--- a/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.md
+++ b/changelogs/SkiaSharp.Views.Maui.Controls/3.0.0/SkiaSharp.Views.Maui.Controls.md
@@ -4,3 +4,56 @@
> Assembly Version Changed: 3.0.0.0 vs 2.88.0.0
+### Namespace SkiaSharp.Views.Maui.Controls
+
+#### Type Changed: SkiaSharp.Views.Maui.Controls.SKCanvasView
+
+Removed interface:
+
+```csharp
+ISKCanvasViewController
+```
+
+Removed method:
+
+```csharp
+protected override Microsoft.Maui.SizeRequest OnMeasure (double widthConstraint, double heightConstraint);
+```
+
+
+#### Type Changed: SkiaSharp.Views.Maui.Controls.SKGLView
+
+Removed interface:
+
+```csharp
+ISKGLViewController
+```
+
+Added interface:
+
+```csharp
+SkiaSharp.Views.Maui.ISKGLView
+```
+
+Added field:
+
+```csharp
+public static Microsoft.Maui.Controls.BindableProperty IgnorePixelScalingProperty;
+```
+
+Added property:
+
+```csharp
+public override bool IgnorePixelScaling { get; set; }
+```
+
+Removed method:
+
+```csharp
+protected override Microsoft.Maui.SizeRequest OnMeasure (double widthConstraint, double heightConstraint);
+```
+
+
+#### Removed Type SkiaSharp.Views.Maui.Controls.ISKCanvasViewController
+#### Removed Type SkiaSharp.Views.Maui.Controls.ISKGLViewController
+
diff --git a/changelogs/SkiaSharp.Views.Maui.Core/3.0.0/SkiaSharp.Views.Maui.Core.md b/changelogs/SkiaSharp.Views.Maui.Core/3.0.0/SkiaSharp.Views.Maui.Core.md
index c6137a6a83..c33e810f4c 100644
--- a/changelogs/SkiaSharp.Views.Maui.Core/3.0.0/SkiaSharp.Views.Maui.Core.md
+++ b/changelogs/SkiaSharp.Views.Maui.Core/3.0.0/SkiaSharp.Views.Maui.Core.md
@@ -4,3 +4,64 @@
> Assembly Version Changed: 3.0.0.0 vs 2.88.0.0
+### Namespace SkiaSharp.Views.Maui
+
+#### Type Changed: SkiaSharp.Views.Maui.SKPaintGLSurfaceEventArgs
+
+Added constructors:
+
+```csharp
+public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKImageInfo info);
+public SKPaintGLSurfaceEventArgs (SkiaSharp.SKSurface surface, SkiaSharp.GRBackendRenderTarget renderTarget, SkiaSharp.GRSurfaceOrigin origin, SkiaSharp.SKImageInfo info, SkiaSharp.SKImageInfo rawInfo);
+```
+
+Added properties:
+
+```csharp
+public SkiaSharp.SKImageInfo Info { get; }
+public SkiaSharp.SKImageInfo RawInfo { get; }
+```
+
+
+#### New Type: SkiaSharp.Views.Maui.ISKGLView
+
+```csharp
+public interface ISKGLView : Microsoft.Maui.IElement, Microsoft.Maui.ITransform, Microsoft.Maui.IView {
+ // properties
+ public virtual SkiaSharp.SKSize CanvasSize { get; }
+ public virtual bool EnableTouchEvents { get; }
+ public virtual SkiaSharp.GRContext GRContext { get; }
+ public virtual bool HasRenderLoop { get; }
+ public virtual bool IgnorePixelScaling { get; }
+ // methods
+ public virtual void InvalidateSurface ();
+ public virtual void OnCanvasSizeChanged (SkiaSharp.SKSizeI size);
+ public virtual void OnGRContextChanged (SkiaSharp.GRContext context);
+ public virtual void OnPaintSurface (SKPaintGLSurfaceEventArgs e);
+ public virtual void OnTouch (SKTouchEventArgs e);
+}
+```
+
+
+### Namespace SkiaSharp.Views.Maui.Handlers
+
+#### New Type: SkiaSharp.Views.Maui.Handlers.SKGLViewHandler
+
+```csharp
+public class SKGLViewHandler : Microsoft.Maui.Handlers.ViewHandler`2[SkiaSharp.Views.Maui.ISKGLView,System.Object], Microsoft.Maui.IElementHandler, Microsoft.Maui.IPlatformViewHandler, Microsoft.Maui.IViewHandler {
+ // constructors
+ public SKGLViewHandler ();
+ public SKGLViewHandler (Microsoft.Maui.PropertyMapper mapper, Microsoft.Maui.CommandMapper commands);
+ // fields
+ public static Microsoft.Maui.CommandMapper SKGLViewCommandMapper;
+ public static Microsoft.Maui.PropertyMapper SKGLViewMapper;
+ // methods
+ protected override object CreatePlatformView ();
+ public static void MapEnableTouchEvents (SKGLViewHandler handler, SkiaSharp.Views.Maui.ISKGLView view);
+ public static void MapHasRenderLoop (SKGLViewHandler handler, SkiaSharp.Views.Maui.ISKGLView view);
+ public static void MapIgnorePixelScaling (SKGLViewHandler handler, SkiaSharp.Views.Maui.ISKGLView view);
+ public static void OnInvalidateSurface (SKGLViewHandler handler, SkiaSharp.Views.Maui.ISKGLView view, object args);
+}
+```
+
+
diff --git a/changelogs/SkiaSharp.Views.WinUI/3.0.0/SkiaSharp.Views.Windows.md b/changelogs/SkiaSharp.Views.WinUI/3.0.0/SkiaSharp.Views.Windows.md
index 82249503c2..bff6e56995 100644
--- a/changelogs/SkiaSharp.Views.WinUI/3.0.0/SkiaSharp.Views.Windows.md
+++ b/changelogs/SkiaSharp.Views.WinUI/3.0.0/SkiaSharp.Views.Windows.md
@@ -27,4 +27,39 @@ public SkiaSharp.GRBackendRenderTargetDesc RenderTarget { get; }
#### Removed Type SkiaSharp.Views.Windows.Extensions
+#### New Type: SkiaSharp.Views.Windows.AngleSwapChainPanel
+
+```csharp
+public class AngleSwapChainPanel : Microsoft.UI.Xaml.Controls.SwapChainPanel {
+ // constructors
+ public AngleSwapChainPanel ();
+ // properties
+ public double ContentsScale { get; }
+ public bool DrawInBackground { get; set; }
+ public bool EnableRenderLoop { get; set; }
+ // methods
+ public void Invalidate ();
+ protected virtual void OnDestroyingContext ();
+ protected virtual void OnRenderFrame (Windows.Foundation.Rect rect);
+}
+```
+
+#### New Type: SkiaSharp.Views.Windows.SKSwapChainPanel
+
+```csharp
+public class SKSwapChainPanel : SkiaSharp.Views.Windows.AngleSwapChainPanel {
+ // constructors
+ public SKSwapChainPanel ();
+ // properties
+ public SkiaSharp.SKSize CanvasSize { get; }
+ public SkiaSharp.GRContext GRContext { get; }
+ // events
+ public event System.EventHandler PaintSurface;
+ // methods
+ protected override void OnDestroyingContext ();
+ protected virtual void OnPaintSurface (SKPaintGLSurfaceEventArgs e);
+ protected override void OnRenderFrame (Windows.Foundation.Rect rect);
+}
+```
+
diff --git a/changelogs/SkiaSharp/3.0.0/SkiaSharp.humanreadable.md b/changelogs/SkiaSharp/3.0.0/SkiaSharp.humanreadable.md
index 70e2d245d2..111da80d82 100644
--- a/changelogs/SkiaSharp/3.0.0/SkiaSharp.humanreadable.md
+++ b/changelogs/SkiaSharp/3.0.0/SkiaSharp.humanreadable.md
@@ -1,22 +1,28 @@
-# API diff: SkiaSharp.dll
-
-## SkiaSharp.dll
-
-> Assembly Version Changed: 3.0.0.0 vs 2.88.0.0
-
-### Major Changes
+# SkiaSharp 3.x Changes
The diff below contains all the changes that are in addition to the removal of obsolete types and members. The 3.x release is a major upgrade and many of the obsolete types and members needed to go away.
-#### Platform Reduction
+**Contents**
-SkiaSharp supports many platforms, however in 3.x we reduce the platforms to just the more modern ones:
+* [Improvements](#improvements)
+ There are many new APIs and improvements to exisitng features.
+* [Breaking Changes](#breaking-changes)
+ In order to update to the latest skia builds and to keep the library maintainable, we unfortunately had to make some hard choices and remove some old APIs.
+ * [Platform Reduction](#platform-reduction)
+ In order to move forward, we had to reduce our supported platforms. However, all the modern and supported .NET platforms are still there.
+ * [ABI Breaking Changes](#abi-breaking-changes)
+ Unfortunately several APIs had to be dropped. This could be that the new skia engine does not support a feature or it was not working previously.
+ * [Removed `[Obsolete]` Types and Members](#removed-obsolete-types-and-members)
+ Several obsolete APIs were removed as they have been marked for removal for several years now. In most cases, there are already alternatives that you can use instead.
+ * [Analysis and Tooling](#analysis-and-tooling)
+ Because some breaking changes are hard to detect and since SkiaSharp is so widely used, we have put together some tooling to help you detect those breaking APIs before you even update.
+* [Newly Obsoleted Types and Members](#newly-obsoleted-types-and-members)
+ The new version of skia does things a bit differently in some places, so some existing APIs are no longer relevant or there are better APIs to use.
+* [API diff: SkiaSharp.dll](#api-diff-skiasharpdll)
+ This is a more readable diff of SkiaSharp as the full diff is really long and has many changes that are not really relevant.
-* .NET Standard 2.0+
-* .NET Framework 4.6.2+
-* .NET 7+ (All the platforms: Android, iOS, Mac Catalyst, macOS, Tizen, tvOS, Windows)
-#### Improvements
+## Improvements
There are some small improvements in the initial release of 3.x, and many more will be added with later builds.
@@ -26,13 +32,23 @@ There are some small improvements in the initial release of 3.x, and many more w
* `SKPoint3` is now implicitly compatible with `System.Numerics.Vector3` in both directions.
* `SKPointI` is now implicitly cast to `System.Numerics.Vector3`.
* `SKRuntimeEffect` now works on both CPU and GPU:
- * GPU is accelerated and support more targets: `SKColorFilter` and `SKShader` (there is also a new `SKBlender` that is not yet exposed in SkiaSharp).
+ * GPU is accelerated and support more targets: `SKColorFilter`, `SKShader` and the new `SKBlender`.
* CPU is NOT accelerated and may be very slow.
* `SKMatrix44` is now a high-performance struct that can be used on any `SKCanvas`.
-#### Breaking Changes
+## Breaking Changes
-With the major update from 2x to 3x, some APIs were broken to make maintainance easier as well as to simplify things for consumers.
+With the major update from 2.x to 3.x, some APIs were broken to make maintainance easier as well as to simplify things for consumers.
+
+### Platform Reduction
+
+SkiaSharp supports many platforms, however in 3.x we reduce the platforms to just the more modern ones:
+
+* .NET Standard 2.0+
+* .NET Framework 4.6.2+
+* .NET 7+ (All the platforms: Android, iOS, Mac Catalyst, macOS, Tizen, tvOS, Windows)
+
+### ABI Breaking Changes
Below is a list of notable breaking changes.
@@ -45,7 +61,7 @@ Below is a list of notable breaking changes.
* `SK3dView` was removed because it was expensive to use
The new `SKMatrix44` can do all the same things as well as just using `System.Numerics.Matrix4x4` and related `System.Numerics` types.
-##### Removed [Obsolete] Types and Members
+### Removed `[Obsolete]` Types and Members
Many types and members were obsoleted at trhe start of the 2.x version (and some before).
The 3.x release will be removing all the members that were previously marked `[Obsolete]`.
@@ -63,9 +79,44 @@ Some of the notable removals are:
* `SKMask` - All types and members relating to `SKMask` have been removed.
* `SKXmlWriter` - All types and members relating to `SKXmlWriter` and `SKXmlStreamWriter` have been removed.
-#### Obsoleted Types and Members
+### Analysis and Tooling
+
+If you are upgrading to SkiaSharp 3.x, you may be interested in using the [`api-tools` .NET CLI tool](https://nuget.org/packages/api-tools) to help identify any usages of removed types.
+
+There is [full documentation available](https://github.com/mattleibow/Mono.ApiTools.NuGetDiff/blob/5c14bf43a6a587c2fd2878c7884ff1db6a9beca1/docs/api-tools.md#compat-command), but the `api-tools` CLI tool can be used to find all usages of missing types and members:
+
+```sh
+dotnet api-tools compat Svg.Skia/Svg.Skia.dll SkiaSharp/v3/SkiaSharp.dll
+```
+
+This will produce an output similar to:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+This output indicates that there are several usages of missing types and members. However, in many cases, there are overloads or alternate APIs that can be used that are present in both 2.x and 3.x versions of SkiaSharp.
+
+
+## Newly Obsoleted Types and Members
-With the major update from 2x to 3x, several APIs are no longer the recommeneded way to do something. There might be a better or cleaner way of doing something. For all of these types and members, they will be marked `[Obsolete]` and removed in the next major release.
+With the major update from 2.x to 3.x, several APIs are no longer the recommeneded way to do something. There might be a better or cleaner way of doing something. For all of these types and members, they will be marked `[Obsolete]` and removed in the next major release.
Some of the notable obsolete items are:
@@ -74,6 +125,10 @@ Some of the notable obsolete items are:
* `SKFont` & `SKPaint` - All the "font-related" members on `SKPaint` have been marked obsolete and now exist on `SKFont`.
In previous skia versions, the `SKPaint` functionality was split into 2 objects: `SKPaint` and `SKFont`. SkiaSharp tried to maintain 100% backwards compatibility by re-merginf the types. However, this is getting hard to maintain. As a result, `SKFont` is now the correct replacement to work with typefaces and character styles. All APIs tha accepted just a `SKPaint` now also have an overload that accepts `SKFont` and `SKTextAlign`.
+## API diff: SkiaSharp.dll
+
+> Assembly Version Changed: 3.0.0.0 vs 2.88.0.0
+
### Namespace SkiaSharp
#### Type Changed: SkiaSharp.GRGlFramebufferInfo
diff --git a/externals/.gitignore b/externals/.gitignore
index df5b644fa9..d83a461853 100644
--- a/externals/.gitignore
+++ b/externals/.gitignore
@@ -1,3 +1,4 @@
angle/
package_cache/
vcpkg/
+winappsdk/
diff --git a/externals/skia b/externals/skia
index 519e4b3025..f1c2f7b424 160000
--- a/externals/skia
+++ b/externals/skia
@@ -1 +1 @@
-Subproject commit 519e4b302588722e71ca71c2531749747a789cf0
+Subproject commit f1c2f7b4246141c6037820dc75d89496ac4aa8b3
diff --git a/interactive/README.dib b/interactive/README.dib
index 75a567c83c..bbe466d809 100644
--- a/interactive/README.dib
+++ b/interactive/README.dib
@@ -4,7 +4,7 @@
Welcome to SkiaSharp, the most awesome, cross-platform 2D-graphics engine. It is powered by the same engine that powers Android and Chrome.
-The first thing we need to do is intsall the package:
+The first thing we need to do is install the package:
#!csharp
diff --git a/native/.gitignore b/native/.gitignore
index 2a4fe393c9..2f11c1ce72 100644
--- a/native/.gitignore
+++ b/native/.gitignore
@@ -1,3 +1,4 @@
xcuserdata/
project.xcworkspace/
uwp/ANGLE/triplets
+Generated Files/
diff --git a/native/linux/libSkiaSharp/libSkiaSharp.map b/native/linux/libSkiaSharp/libSkiaSharp.map
index efb3ef0c45..c10403496d 100644
--- a/native/linux/libSkiaSharp/libSkiaSharp.map
+++ b/native/linux/libSkiaSharp/libSkiaSharp.map
@@ -4,6 +4,7 @@ libSkiaSharp {
gr_*;
skottie_*;
sksg_*;
+ skresources_*;
local:
*;
};
diff --git a/native/windows/build.cake b/native/windows/build.cake
index 98f1bd2b8c..db7dfc7ff7 100644
--- a/native/windows/build.cake
+++ b/native/windows/build.cake
@@ -1,7 +1,8 @@
DirectoryPath ROOT_PATH = MakeAbsolute(Directory("../.."));
DirectoryPath OUTPUT_PATH = MakeAbsolute(ROOT_PATH.Combine("output/native"));
-DirectoryPath LLVM_HOME = Argument("llvm", EnvironmentVariable("LLVM_HOME") ?? "C:/Program Files/LLVM");
+var llvmHomeArg = Argument("llvm", EnvironmentVariable("LLVM_HOME") ?? "C:/Program Files/LLVM");
+DirectoryPath LLVM_HOME = string.IsNullOrEmpty(llvmHomeArg) || llvmHomeArg.ToLower() == "msvc" ? "" : llvmHomeArg;
string VC_TOOLSET_VERSION = Argument("vcToolsetVersion", "14.2");
string SUPPORT_VULKAN_VAR = Argument ("supportVulkan", EnvironmentVariable ("SUPPORT_VULKAN") ?? "true");
@@ -13,7 +14,7 @@ bool SUPPORT_VULKAN = SUPPORT_VULKAN_VAR == "1" || SUPPORT_VULKAN_VAR.ToLower ()
string VARIANT = BUILD_VARIANT ?? "windows";
Information("Native Arguments:");
-Information($" {"LLVM_HOME".PadRight(30)} {{0}}", LLVM_HOME);
+Information($" {"LLVM_HOME".PadRight(30)} {{0}}", string.IsNullOrEmpty(LLVM_HOME.FullPath) ? "(Using MSVC)" : LLVM_HOME);
Information($" {"SUPPORT_VULKAN".PadRight(30)} {{0}}", SUPPORT_VULKAN);
Information($" {"VARIANT".PadRight(30)} {{0}}", VARIANT);
Information($" {"CONFIGURATION".PadRight(30)} {{0}}", CONFIGURATION);
@@ -54,7 +55,7 @@ Task("libSkiaSharp")
clang +
win_vcvars_version +
$"extra_cflags=[ '-DSKIA_C_DLL', '/MT{d}', '/EHsc', '/Z7', '-D_HAS_AUTO_PTR_ETC=1' ] " +
- $"extra_ldflags=[ '/DEBUG:FULL' ] " +
+ $"extra_ldflags=[ '/DEBUG:FULL', '/DEBUGTYPE:CV,FIXUP' ] " +
ADDITIONAL_GN_ARGS);
var outDir = OUTPUT_PATH.Combine($"{VARIANT}/{dir}");
diff --git a/native/windows/libHarfBuzzSharp/libHarfBuzzSharp.vcxproj b/native/windows/libHarfBuzzSharp/libHarfBuzzSharp.vcxproj
index 0589d79fb2..bd752caa19 100644
--- a/native/windows/libHarfBuzzSharp/libHarfBuzzSharp.vcxproj
+++ b/native/windows/libHarfBuzzSharp/libHarfBuzzSharp.vcxproj
@@ -148,6 +148,7 @@
Windows
+ /DEBUGTYPE:CV,FIXUP
@@ -163,6 +164,7 @@
Windows
+ /DEBUGTYPE:CV,FIXUP
@@ -178,6 +180,7 @@
Windows
+ /DEBUGTYPE:CV,FIXUP
@@ -197,6 +200,7 @@
Windows
true
true
+ /DEBUGTYPE:CV,FIXUP
@@ -216,6 +220,7 @@
Windows
true
true
+ /DEBUGTYPE:CV,FIXUP
@@ -235,6 +240,7 @@
Windows
true
true
+ /DEBUGTYPE:CV,FIXUP
diff --git a/native/winui/ANGLE.cake b/native/winui/ANGLE.cake
new file mode 100644
index 0000000000..5fe7e4285d
--- /dev/null
+++ b/native/winui/ANGLE.cake
@@ -0,0 +1,75 @@
+void InitializeAngle(string branch, DirectoryPath ANGLE_PATH, DirectoryPath WINAPPSDK_PATH)
+{
+ if (!DirectoryExists(ANGLE_PATH)) {
+ RunProcess("git", $"clone https://github.com/google/angle.git --branch {branch} --depth 1 --single-branch --shallow-submodules {ANGLE_PATH}");
+ }
+
+ var submodules = new[] {
+ "build",
+ "testing",
+ "third_party/zlib",
+ "third_party/jsoncpp",
+ "third_party/vulkan-deps",
+ "third_party/astc-encoder/src",
+ "tools/clang",
+ };
+ foreach (var submodule in submodules) {
+ var sub = ANGLE_PATH.Combine(submodule);
+ if (FileExists(sub.CombineWithFilePath("BUILD.gn")) || FileExists(sub.CombineWithFilePath(".gitignore")))
+ continue;
+
+ RunProcess("git", new ProcessSettings {
+ Arguments = $"submodule update --init --recursive --depth 1 --single-branch {submodule}",
+ WorkingDirectory = ANGLE_PATH.FullPath,
+ });
+ }
+
+ {
+ var toolchain = ANGLE_PATH.CombineWithFilePath("build/toolchain/win/toolchain.gni");
+ var contents = System.IO.File.ReadAllText(toolchain.FullPath);
+ var newContents = contents
+ .Replace("\"${dllname}.lib\"", "\"{{output_dir}}/{{target_output_name}}.lib\"")
+ .Replace("\"${dllname}.pdb\"", "\"{{output_dir}}/{{target_output_name}}.pdb\"");
+ if (contents != newContents)
+ System.IO.File.WriteAllText(toolchain.FullPath, newContents);
+ }
+
+ if (!FileExists(ANGLE_PATH.CombineWithFilePath("build/config/gclient_args.gni"))) {
+ var lines = new[] {
+ "checkout_angle_internal = false",
+ "checkout_angle_mesa = false",
+ "checkout_angle_restricted_traces = false",
+ "generate_location_tags = false"
+ };
+ System.IO.File.WriteAllLines(ANGLE_PATH.CombineWithFilePath("build/config/gclient_args.gni").FullPath, lines);
+ }
+
+ if (!FileExists(ANGLE_PATH.CombineWithFilePath("build/util/LASTCHANGE"))) {
+ var lastchange = ANGLE_PATH.CombineWithFilePath("build/util/LASTCHANGE");
+ RunPython(ANGLE_PATH, ANGLE_PATH.CombineWithFilePath("build/util/lastchange.py"), $"-o {lastchange}");
+ }
+
+ if (!FileExists(ANGLE_PATH.CombineWithFilePath("build/toolchain/win/rc/win/rc.exe"))) {
+ var oldPath = EnvironmentVariable("PATH");
+ try {
+ System.Environment.SetEnvironmentVariable("PATH", DEPOT_PATH.FullPath + System.IO.Path.PathSeparator + oldPath);
+
+ RunPython(ANGLE_PATH,
+ DEPOT_PATH.CombineWithFilePath("download_from_google_storage.py"),
+ $"--no_resume --no_auth --bucket chromium-browser-clang/rc -s build/toolchain/win/rc/win/rc.exe.sha1");
+ } finally {
+ System.Environment.SetEnvironmentVariable("PATH", oldPath);
+ }
+ }
+
+ if (!FileExists(ANGLE_PATH.CombineWithFilePath("third_party/llvm-build/Release+Asserts/cr_build_revision"))) {
+ RunPython(ANGLE_PATH, ANGLE_PATH.CombineWithFilePath("tools/clang/scripts/update.py"));
+ }
+
+ if (!FileExists(WINAPPSDK_PATH.CombineWithFilePath("Microsoft.WindowsAppSDK.nuspec"))) {
+ var setup = ANGLE_PATH.CombineWithFilePath("scripts/winappsdk_setup.py");
+ RunProcess(
+ ROOT_PATH.CombineWithFilePath("scripts/vcvarsall.bat"),
+ $"\"{VS_INSTALL}\" \"x64\" \"{PYTHON_EXE}\" \"{setup}\" --output \"{WINAPPSDK_PATH}\"");
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props
new file mode 100644
index 0000000000..67ea2536c9
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets
new file mode 100644
index 0000000000..3d8b24a04d
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/Directory.Build.targets
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj
new file mode 100644
index 0000000000..85615cef2f
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.Projection/SkiaSharp.Views.WinUI.Native.Projection.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net7.0-windows10.0.19041.0
+ 10.0.17763.0
+ SkiaSharp.Views.WinUI
+ SkiaSharp.Views.WinUI
+ false
+ enable
+ enable
+
+
+
+ None
+ SkiaSharp.Views.WinUI.Native
+
+
+
+
+
+
+
+
+
+
+
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln
new file mode 100644
index 0000000000..0435478c90
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln
@@ -0,0 +1,61 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34310.174
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SkiaSharp.Views.WinUI.Native", "SkiaSharp.Views.WinUI.Native\SkiaSharp.Views.WinUI.Native.vcxproj", "{730AF4C9-82D2-4FA7-AA32-154F3524EBD2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.WinUI.Native.Projection", "SkiaSharp.Views.WinUI.Native.Projection\SkiaSharp.Views.WinUI.Native.Projection.csproj", "{95E9FEB4-DCD3-4514-8208-A87688788BB2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|Any CPU.Build.0 = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|ARM64.Build.0 = Debug|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x64.ActiveCfg = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x64.Build.0 = Debug|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x86.ActiveCfg = Debug|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Debug|x86.Build.0 = Debug|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|Any CPU.ActiveCfg = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|Any CPU.Build.0 = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|ARM64.ActiveCfg = Release|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|ARM64.Build.0 = Release|ARM64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x64.ActiveCfg = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x64.Build.0 = Release|x64
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x86.ActiveCfg = Release|Win32
+ {730AF4C9-82D2-4FA7-AA32-154F3524EBD2}.Release|x86.Build.0 = Release|Win32
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x64.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Debug|x86.Build.0 = Debug|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|ARM64.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x64.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x64.Build.0 = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x86.ActiveCfg = Release|Any CPU
+ {95E9FEB4-DCD3-4514-8208-A87688788BB2}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FB8DA12F-84B5-4D7F-A6E1-7F0A53AA4535}
+ EndGlobalSection
+EndGlobal
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp
new file mode 100644
index 0000000000..c2174e6cf7
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.cpp
@@ -0,0 +1,19 @@
+#include "pch.h"
+#include "PropertySetExtensions.h"
+#include "PropertySetExtensions.g.cpp"
+
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ void PropertySetExtensions::AddSingle(PropertySet const& propertySet, hstring const& key, float value)
+ {
+ propertySet.Insert(key, PropertyValue::CreateSingle(value));
+ }
+
+ void PropertySetExtensions::AddSize(PropertySet const& propertySet, hstring const& key, Size const& height)
+ {
+ propertySet.Insert(key, PropertyValue::CreateSize(height));
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h
new file mode 100644
index 0000000000..de60e32b45
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "PropertySetExtensions.g.h"
+
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::implementation
+{
+ struct PropertySetExtensions
+ {
+ PropertySetExtensions() = default;
+
+ static void AddSingle(PropertySet const& propertySet, hstring const& key, float value);
+ static void AddSize(PropertySet const& propertySet, hstring const& key, Size const& value);
+ };
+}
+
+namespace winrt::SkiaSharp::Views::WinUI::Native::factory_implementation
+{
+ struct PropertySetExtensions : PropertySetExtensionsT
+ {
+ };
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl
new file mode 100644
index 0000000000..278b3c896c
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/PropertySetExtensions.idl
@@ -0,0 +1,8 @@
+namespace SkiaSharp.Views.WinUI.Native
+{
+ static runtimeclass PropertySetExtensions
+ {
+ static void AddSingle(Windows.Foundation.Collections.PropertySet propertySet, String key, Single value);
+ static void AddSize(Windows.Foundation.Collections.PropertySet propertySet, String key, Windows.Foundation.Size value);
+ }
+}
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj
new file mode 100644
index 0000000000..3906b7d76f
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+ true
+ true
+ true
+ {730af4c9-82d2-4fa7-aa32-154f3524ebd2}
+ SkiaSharp.Views.WinUI.Native
+ SkiaSharp.Views.WinUI.Native
+ en-US
+ 16.0
+ false
+ Windows Store
+ 10.0
+ 10.0.22621.0
+ 10.0.17763.0
+ true
+ true
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+ Release
+ ARM64
+
+
+
+ DynamicLibrary
+ v143
+ Unicode
+ false
+ true
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(ProjectDir)bin\$(Platform)\$(Configuration)\
+ $(ProjectDir)obj\$(Platform)\$(Configuration)\
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+
+
+ Console
+ true
+ SkiaSharp_Views_WinUI_Native.def
+ /DEBUGTYPE:CV,FIXUP
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+ PropertySetExtensions.cpp
+
+
+
+
+ Create
+
+
+
+
+
+
+ Code
+ PropertySetExtensions.cpp
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters
new file mode 100644
index 0000000000..099f47d334
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ accd3aa8-1ba0-4223-9bbe-0c431709210b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {926ab91d-31b4-48c3-b9a4-e681349f27f0}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def
new file mode 100644
index 0000000000..24e7c1235c
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/SkiaSharp_Views_WinUI_Native.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config
new file mode 100644
index 0000000000..152b1d8ec4
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp
new file mode 100644
index 0000000000..1d9f38c57d
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h"
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h
new file mode 100644
index 0000000000..1533d96bb2
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/pch.h
@@ -0,0 +1,26 @@
+#pragma once
+#include
+#include
+#include
+#include
+
+// Undefine GetCurrentTime macro to prevent
+// conflict with Storyboard::GetCurrentTime
+#undef GetCurrentTime
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
diff --git a/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt
new file mode 100644
index 0000000000..fd4c59a522
--- /dev/null
+++ b/native/winui/SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native/readme.txt
@@ -0,0 +1,27 @@
+========================================================================
+ SkiaSharp.Views.WinUI.Native Project Overview
+========================================================================
+
+This project demonstrates how to get started authoring Windows Runtime
+classes directly with standard C++, using the Windows App SDK and
+C++/WinRT packages to generate implementation headers from interface
+(IDL) files. The generated Windows Runtime component binary and WinMD
+files should then be bundled with the app consuming them.
+
+Steps:
+1. Create an interface (IDL) file to define your Windows Runtime class,
+ its default interface, and any other interfaces it implements.
+2. Build the project once to generate module.g.cpp, module.h.cpp, and
+ implementation templates under the "Generated Files" folder, as
+ well as skeleton class definitions under "Generated Files\sources".
+3. Use the skeleton class definitions for reference to implement your
+ Windows Runtime classes.
+
+========================================================================
+Learn more about Windows App SDK here:
+https://docs.microsoft.com/windows/apps/windows-app-sdk/
+Learn more about WinUI3 here:
+https://docs.microsoft.com/windows/apps/winui/winui3/
+Learn more about C++/WinRT here:
+http://aka.ms/cppwinrt/
+========================================================================
diff --git a/native/winui/build.cake b/native/winui/build.cake
new file mode 100644
index 0000000000..7409df544f
--- /dev/null
+++ b/native/winui/build.cake
@@ -0,0 +1,93 @@
+DirectoryPath ROOT_PATH = MakeAbsolute(Directory("../.."));
+DirectoryPath OUTPUT_PATH = MakeAbsolute(ROOT_PATH.Combine("output/native/winui"));
+
+#load "../../scripts/cake/native-shared.cake"
+#load "../../scripts/cake/msbuild.cake"
+
+#load "ANGLE.cake"
+
+Task("ANGLE")
+ .IsDependentOn("git-sync-deps")
+ .WithCriteria(IsRunningOnWindows())
+ .Does(() =>
+{
+ var ANGLE_PATH = ROOT_PATH.Combine("externals/angle");
+ var WINAPPSDK_PATH = ROOT_PATH.Combine("externals/winappsdk");
+
+ var branch = GetVersion("ANGLE", "release");
+
+ InitializeAngle(branch, ANGLE_PATH, WINAPPSDK_PATH);
+
+ Build("x86");
+ Build("x64");
+ Build("arm64");
+
+ void Build(string arch)
+ {
+ if (Skip(arch)) return;
+
+ try {
+ System.Environment.SetEnvironmentVariable("DEPOT_TOOLS_WIN_TOOLCHAIN", "0");
+
+ RunGn(ANGLE_PATH, $"out/winui/{arch}",
+ $"target_cpu='{arch}' " +
+ $"is_component_build=false " +
+ $"is_debug=false " +
+ $"is_clang=false " +
+ $"angle_is_winappsdk=true " +
+ $"winappsdk_dir='{WINAPPSDK_PATH}' " +
+ $"enable_precompiled_headers=false " +
+ $"angle_enable_null=false " +
+ $"angle_enable_wgpu=false " +
+ $"angle_enable_gl_desktop_backend=false " +
+ $"angle_enable_vulkan=false");
+
+ RunNinja(ANGLE_PATH, $"out/winui/{arch}", "libEGL libGLESv2");
+ } finally {
+ System.Environment.SetEnvironmentVariable("DEPOT_TOOLS_WIN_TOOLCHAIN", "");
+ }
+
+ var outDir = OUTPUT_PATH.Combine(arch);
+ EnsureDirectoryExists(outDir);
+ CopyFileToDirectory(ANGLE_PATH.CombineWithFilePath($"out/winui/{arch}/libEGL.dll"), outDir);
+ CopyFileToDirectory(ANGLE_PATH.CombineWithFilePath($"out/winui/{arch}/libEGL.pdb"), outDir);
+ CopyFileToDirectory(ANGLE_PATH.CombineWithFilePath($"out/winui/{arch}/libGLESv2.dll"), outDir);
+ CopyFileToDirectory(ANGLE_PATH.CombineWithFilePath($"out/winui/{arch}/libGLESv2.pdb"), outDir);
+ }
+});
+
+Task("SkiaSharp.Views.WinUI.Native")
+ .WithCriteria(IsRunningOnWindows())
+ .Does(() =>
+{
+ Build("x86", "Win32");
+ Build("x64", "x64");
+ Build("arm64", "arm64");
+
+ void Build(string arch, string nativeArch)
+ {
+ if (Skip(arch)) return;
+
+ RunProcess("nuget", "restore SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln");
+ RunMSBuild("SkiaSharp.Views.WinUI.Native/SkiaSharp.Views.WinUI.Native.sln", arch);
+
+ var name = "SkiaSharp.Views.WinUI.Native";
+
+ var outDir = OUTPUT_PATH.Combine(arch);
+ EnsureDirectoryExists(outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.dll", outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.pdb", outDir);
+ CopyFileToDirectory($"{name}/{name}/bin/{nativeArch}/{CONFIGURATION}/{name}.winmd", outDir);
+
+ var anyOutDir = OUTPUT_PATH.Combine("any");
+ EnsureDirectoryExists(anyOutDir);
+ CopyFileToDirectory($"{name}/{name}.Projection/bin/{CONFIGURATION}/net7.0-windows10.0.19041.0/{name}.Projection.dll", anyOutDir);
+ CopyFileToDirectory($"{name}/{name}.Projection/bin/{CONFIGURATION}/net7.0-windows10.0.19041.0/{name}.Projection.pdb", anyOutDir);
+ }
+});
+
+Task("Default")
+ .IsDependentOn("ANGLE")
+ .IsDependentOn("SkiaSharp.Views.WinUI.Native");
+
+RunTarget(TARGET);
diff --git a/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj
index 1fea779096..9b5b1c5498 100644
--- a/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj
+++ b/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj
@@ -37,5 +37,6 @@
+
diff --git a/samples/Basic/WinUI/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/WinUI/SkiaSharpSample/SkiaSharpSample.csproj
index c46e450c1e..40fc8e00b0 100644
--- a/samples/Basic/WinUI/SkiaSharpSample/SkiaSharpSample.csproj
+++ b/samples/Basic/WinUI/SkiaSharpSample/SkiaSharpSample.csproj
@@ -12,7 +12,7 @@
-
+
@@ -32,5 +32,6 @@
+
diff --git a/scripts/VERSIONS.txt b/scripts/VERSIONS.txt
index a7c9249bfa..536f5bafc3 100644
--- a/scripts/VERSIONS.txt
+++ b/scripts/VERSIONS.txt
@@ -1,7 +1,7 @@
# dependencies
mdoc release 5.8.9
harfbuzz release 8.3.0
-skia release m115
+skia release m116
xunit release 2.4.2
xunit.runner.console release 2.4.2
OpenTK release 3.1.0
@@ -17,17 +17,18 @@ Microsoft.WindowsAppSDK release 1.3.230602002
Microsoft.Maui.Graphics release 7.0.92
Microsoft.Windows.SDK.NET.Ref release 10.0.19041.27
Microsoft.AspNetCore.Components.Web release 6.0.0
+ANGLE release chromium/6275
# native milestones
# this is related to the API versions, not the library versions
# - milestone: the skia milestone determined by Google/Chromium
# - increment: the C API version increment caused by new APIs (externals\skia\include\c\sk_types.h)
-libSkiaSharp milestone 115
+libSkiaSharp milestone 116
libSkiaSharp increment 0
# native sonames
# ..0
-libSkiaSharp soname 115.0.0
+libSkiaSharp soname 116.0.0
# 0.<60000 + major*100 + minor*10 + micro>.0
HarfBuzz soname 0.60830.0
@@ -53,6 +54,7 @@ SkiaSharp.NativeAssets.macOS nuget 3.0.0
SkiaSharp.NativeAssets.Tizen nuget 3.0.0
SkiaSharp.NativeAssets.tvOS nuget 3.0.0
SkiaSharp.NativeAssets.Win32 nuget 3.0.0
+SkiaSharp.NativeAssets.WinUI nuget 3.0.0
SkiaSharp.Views nuget 3.0.0
SkiaSharp.Views.Desktop.Common nuget 3.0.0
SkiaSharp.Views.Gtk3 nuget 3.0.0
@@ -66,6 +68,7 @@ SkiaSharp.Views.Blazor nuget 3.0.0
SkiaSharp.HarfBuzz nuget 3.0.0
SkiaSharp.Skottie nuget 3.0.0
SkiaSharp.SceneGraph nuget 3.0.0
+SkiaSharp.Resources nuget 3.0.0
SkiaSharp.Vulkan.SharpVk nuget 3.0.0
# HarfBuzzSharp
HarfBuzzSharp nuget 8.3.0
diff --git a/scripts/azure-pipelines-complete-internal.yml b/scripts/azure-pipelines-complete-internal.yml
index 56a0d9b61b..394a5de69d 100644
--- a/scripts/azure-pipelines-complete-internal.yml
+++ b/scripts/azure-pipelines-complete-internal.yml
@@ -4,43 +4,56 @@ pr: none
parameters:
- name: buildExternals
- displayName: 'The specific native artifacts to use for this build.'
+ displayName: 'The Build ID containing the specific native artifacts to use:'
type: string
default: 'latest'
- - name: VM_IMAGE_HOST
+ - name: buildAgentHost
+ displayName: 'The generic host build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
- - name: VM_IMAGE_WINDOWS
+ os: windows
+ - name: buildAgentWindows
+ displayName: 'The Windows build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: windows-2022
- - name: VM_IMAGE_MAC
+ os: windows
+ - name: buildAgentMac
+ displayName: 'The macOS build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: macos-13
- - name: VM_IMAGE_LINUX
+ os: macos
+ - name: buildAgentLinux
+ displayName: 'The Linux build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
+ os: linux
+ - name: enableSigning
+ displayName: 'Enable package signing (Test signing)'
+ type: boolean
+ default: false
- name: runCompliance
+ displayName: 'Run post-build compliance tasks (such as API Scan and PoliCheck)'
+ type: boolean
+ default: false
+ - name: use1ESPipelineTemplates
+ displayName: 'Run the build using the internal 1ES Pipeline Templates'
type: boolean
default: false
-
-pool:
- name: Azure Pipelines
- vmImage: ubuntu-20.04
variables:
- - template: azure-pipelines-variables.yml
+ - template: /scripts/azure-pipelines-variables.yml@self
resources:
repositories:
@@ -49,17 +62,51 @@ resources:
name: xamarin/yaml-templates
endpoint: xamarin
ref: refs/heads/main
+ - repository: 1ESPipelineTemplates
+ type: git
+ name: 1ESPipelineTemplates/1ESPipelineTemplates
+ ref: refs/tags/release
-stages:
- - template: azure-templates-stages.yml
- parameters:
- buildPipelineType: 'both'
- buildExternals: ${{ parameters.buildExternals }}
- runCompliance: ${{ parameters.runCompliance }}
- VM_IMAGE_HOST: ${{ parameters.VM_IMAGE_HOST }}
- VM_IMAGE_WINDOWS: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_WINDOWS_NATIVE: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_MAC: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_LINUX: ${{ parameters.VM_IMAGE_LINUX }}
- VM_IMAGE_LINUX_NATIVE: ${{ parameters.VM_IMAGE_LINUX }}
+extends:
+ ${{ if eq('${{ parameters.use1ESPipelineTemplates }}', 'true') }}:
+ template: v1/1ES.Unofficial.PipelineTemplate.yml@1ESPipelineTemplates
+ ${{ if ne('${{ parameters.use1ESPipelineTemplates }}', 'true') }}:
+ template: /scripts/azure-template.yml@self
+ parameters:
+ pool: ${{ parameters.buildAgentHost.pool }}
+ customBuildTags:
+ - ES365AIMigrationTooling
+ stages:
+ - template: /scripts/azure-templates-stages.yml@self
+ parameters:
+ buildPipelineType: 'both'
+ buildExternals: ${{ parameters.buildExternals }}
+ enableSigning: ${{ parameters.enableSigning }}
+ ${{ if eq(parameters.runCompliance, 'true') }}:
+ sdl:
+ apiscan:
+ enabled: true
+ binskim:
+ break: false
+ codeInspector:
+ enabled: true
+ credscan:
+ suppressionsFile: $(Build.SourcesDirectory)\scripts\guardian\CredScanSuppressions.json
+ policheck:
+ enabled: true
+ exclusionsFile: $(Build.SourcesDirectory)\scripts\guardian\PoliCheckExclusions.xml
+ spotBugs:
+ enabled: false
+ suppression:
+ suppressionFile: $(Build.SourcesDirectory)\scripts\guardian\source.gdnsuppress
+ tsa:
+ enabled: true
+ configFile: $(Build.SourcesDirectory)\scripts\guardian\tsaoptions-v2.json
+ use1ESPipelineTemplates: ${{ parameters.use1ESPipelineTemplates }}
+ buildAgentHost: ${{ parameters.buildAgentHost }}
+ buildAgentWindows: ${{ parameters.buildAgentWindows }}
+ buildAgentWindowsNative: ${{ parameters.buildAgentWindows }}
+ buildAgentMac: ${{ parameters.buildAgentMac }}
+ buildAgentMacNative: ${{ parameters.buildAgentMac }}
+ buildAgentLinux: ${{ parameters.buildAgentLinux }}
+ buildAgentLinuxNative: ${{ parameters.buildAgentLinux }}
\ No newline at end of file
diff --git a/scripts/azure-pipelines-complete.yml b/scripts/azure-pipelines-complete.yml
index f0c44874d6..f3deca19b0 100644
--- a/scripts/azure-pipelines-complete.yml
+++ b/scripts/azure-pipelines-complete.yml
@@ -10,50 +10,58 @@ pr:
parameters:
- name: buildExternals
- displayName: 'The specific native artifacts to use for this build.'
+ displayName: 'The Build ID containing the specific native artifacts to use:'
type: string
default: 'latest'
- - name: VM_IMAGE_HOST
+ - name: buildAgentHost
+ displayName: 'The generic host build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
- - name: VM_IMAGE_WINDOWS
+ os: windows
+ - name: buildAgentWindows
+ displayName: 'The Windows build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: windows-2022
- - name: VM_IMAGE_MAC
+ os: windows
+ - name: buildAgentMac
+ displayName: 'The macOS build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: macos-13
- - name: VM_IMAGE_LINUX
+ os: macos
+ - name: buildAgentLinux
+ displayName: 'The Linux build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
-
-pool:
- name: Azure Pipelines
- vmImage: ubuntu-20.04
+ os: linux
variables:
- - template: azure-pipelines-variables.yml
+ - template: /scripts/azure-pipelines-variables.yml@self
-stages:
- - template: azure-templates-stages.yml
- parameters:
- buildPipelineType: 'both'
- buildExternals: ${{ parameters.buildExternals }}
- VM_IMAGE_HOST: ${{ parameters.VM_IMAGE_HOST }}
- VM_IMAGE_WINDOWS: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_WINDOWS_NATIVE: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_MAC: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_LINUX: ${{ parameters.VM_IMAGE_LINUX }}
- VM_IMAGE_LINUX_NATIVE: ${{ parameters.VM_IMAGE_LINUX }}
+extends:
+ template: /scripts/azure-template.yml@self
+ parameters:
+ pool: ${{ parameters.buildAgentHost.pool }}
+ stages:
+ - template: /scripts/azure-templates-stages.yml@self
+ parameters:
+ buildPipelineType: 'both'
+ buildExternals: ${{ parameters.buildExternals }}
+ buildAgentHost: ${{ parameters.buildAgentHost }}
+ buildAgentWindows: ${{ parameters.buildAgentWindows }}
+ buildAgentWindowsNative: ${{ parameters.buildAgentWindows }}
+ buildAgentMac: ${{ parameters.buildAgentMac }}
+ buildAgentMacNative: ${{ parameters.buildAgentMac }}
+ buildAgentLinux: ${{ parameters.buildAgentLinux }}
+ buildAgentLinuxNative: ${{ parameters.buildAgentLinux }}
diff --git a/scripts/azure-pipelines-tests.yml b/scripts/azure-pipelines-tests.yml
index 1127a2e8cb..f7dc37e227 100644
--- a/scripts/azure-pipelines-tests.yml
+++ b/scripts/azure-pipelines-tests.yml
@@ -3,33 +3,41 @@ trigger: none
pr: none
parameters:
- - name: VM_IMAGE_HOST
+ - name: buildAgentHost
+ displayName: 'The generic host build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
- - name: VM_IMAGE_WINDOWS
+ os: windows
+ - name: buildAgentWindows
+ displayName: 'The Windows build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: windows-2022
- - name: VM_IMAGE_MAC
+ os: windows
+ - name: buildAgentMac
+ displayName: 'The macOS build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: macos-13
- - name: VM_IMAGE_LINUX
+ os: macos
+ - name: buildAgentLinux
+ displayName: 'The Linux build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: ubuntu-20.04
+ os: linux
variables:
- - template: azure-pipelines-variables.yml
+ - template: /scripts/azure-pipelines-variables.yml@self
resources:
repositories:
@@ -43,14 +51,18 @@ resources:
source: SkiaSharp
trigger: true
-stages:
- - template: azure-templates-stages.yml
- parameters:
- buildPipelineType: 'tests'
- VM_IMAGE_HOST: ${{ parameters.VM_IMAGE_HOST }}
- VM_IMAGE_WINDOWS: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_WINDOWS_NATIVE: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_MAC: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_LINUX: ${{ parameters.VM_IMAGE_LINUX }}
- VM_IMAGE_LINUX_NATIVE: ${{ parameters.VM_IMAGE_LINUX }}
+extends:
+ template: /scripts/azure-template.yml@self
+ parameters:
+ pool: ${{ parameters.buildAgentHost.pool }}
+ stages:
+ - template: /scripts/azure-templates-stages.yml@self
+ parameters:
+ buildPipelineType: 'tests'
+ buildAgentHost: ${{ parameters.buildAgentHost }}
+ buildAgentWindows: ${{ parameters.buildAgentWindows }}
+ buildAgentWindowsNative: ${{ parameters.buildAgentWindows }}
+ buildAgentMac: ${{ parameters.buildAgentMac }}
+ buildAgentMacNative: ${{ parameters.buildAgentMac }}
+ buildAgentLinux: ${{ parameters.buildAgentLinux }}
+ buildAgentLinuxNative: ${{ parameters.buildAgentLinux }}
\ No newline at end of file
diff --git a/scripts/azure-pipelines-variables.yml b/scripts/azure-pipelines-variables.yml
index 53e405a4af..ef6f1c7c03 100644
--- a/scripts/azure-pipelines-variables.yml
+++ b/scripts/azure-pipelines-variables.yml
@@ -1,4 +1,5 @@
variables:
+ SKIASHARP_MAJOR_VERSION: 3
SKIASHARP_VERSION: 3.0.0
FEATURE_NAME_PREFIX: 'feature/'
VERBOSITY: normal
@@ -16,7 +17,7 @@ variables:
VISUAL_STUDIO_VERSION: ''
DOTNET_VERSION_PREVIEW: ''
DOTNET_WORKLOAD_SOURCE: ''
- DOTNET_WORKLOAD_TIZEN: ''
+ DOTNET_WORKLOAD_TIZEN: '7.0.123'
CONFIGURATION: 'Release'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
NUGET_DIFF_PRERELEASE: false
diff --git a/scripts/azure-pipelines.yml b/scripts/azure-pipelines.yml
index 3b72b46332..30e6bcb5e8 100644
--- a/scripts/azure-pipelines.yml
+++ b/scripts/azure-pipelines.yml
@@ -10,36 +10,48 @@ pr:
parameters:
- name: buildExternals
- displayName: 'The specific native artifacts to use for this build.'
+ displayName: 'The Build ID containing the specific native artifacts to use:'
type: string
default: 'latest'
- - name: VM_IMAGE_HOST
+ - name: buildAgentHost
+ displayName: 'The generic host build agent configuration:'
type: object
default:
pool:
- name: Azure Pipelines
- vmImage: ubuntu-20.04
- - name: VM_IMAGE_WINDOWS
+ name: Maui-1ESPT
+ image: 1ESPT-Windows2022
+ os: windows
+ - name: buildAgentWindows
+ displayName: 'The Windows build agent configuration:'
type: object
default:
pool:
- name: Azure Pipelines
- vmImage: windows-2022
- - name: VM_IMAGE_MAC
+ name: Maui-1ESPT
+ image: 1ESPT-Windows2022
+ os: windows
+ - name: buildAgentMac
+ displayName: 'The macOS build agent configuration:'
type: object
default:
pool:
name: Azure Pipelines
vmImage: macos-13
- - name: VM_IMAGE_LINUX
+ os: macos
+ - name: buildAgentLinux
+ displayName: 'The Linuk build agent configuration:'
type: object
default:
pool:
- name: Azure Pipelines
- vmImage: ubuntu-20.04
+ name: Maui-1ESPT
+ image: 1ESPT-Ubuntu20.04
+ os: linux
+ - name: runCompliance
+ displayName: 'Run post-build compliance tasks (such as API Scan and PoliCheck)'
+ type: boolean
+ default: false
variables:
- - template: azure-pipelines-variables.yml
+ - template: /scripts/azure-pipelines-variables.yml@self
resources:
repositories:
@@ -48,16 +60,51 @@ resources:
name: xamarin/yaml-templates
endpoint: xamarin
ref: refs/heads/main
+ - repository: 1ESPipelineTemplates
+ type: git
+ name: 1ESPipelineTemplates/1ESPipelineTemplates
+ ref: refs/tags/release
-stages:
- - template: azure-templates-stages.yml
- parameters:
- buildPipelineType: 'build'
- buildExternals: ${{ parameters.buildExternals }}
- VM_IMAGE_HOST: ${{ parameters.VM_IMAGE_HOST }}
- VM_IMAGE_WINDOWS: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_WINDOWS_NATIVE: ${{ parameters.VM_IMAGE_WINDOWS }}
- VM_IMAGE_MAC: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_MAC_NATIVE: ${{ parameters.VM_IMAGE_MAC }}
- VM_IMAGE_LINUX: ${{ parameters.VM_IMAGE_LINUX }}
- VM_IMAGE_LINUX_NATIVE: ${{ parameters.VM_IMAGE_LINUX }}
+extends:
+ template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates
+ parameters:
+ pool: ${{ parameters.buildAgentHost.pool }}
+ customBuildTags:
+ - ES365AIMigrationTooling
+ stages:
+ - template: /scripts/azure-templates-stages.yml@self
+ parameters:
+ buildPipelineType: 'build'
+ buildExternals: ${{ parameters.buildExternals }}
+ ${{ if and(eq(variables['System.TeamProject'], 'devdiv'), ne(variables['System.PullRequest.IsFork'], 'true')) }}:
+ enableSigning: true
+ ${{ if or(parameters.runCompliance, and(eq(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')))) }}:
+ sdl:
+ apiscan:
+ enabled: true
+ binskim:
+ enabled: true
+ break: false
+ codeInspector:
+ enabled: true
+ credscan:
+ enabled: true
+ # suppressionsFile: $(Build.SourcesDirectory)\scripts\guardian\CredScanSuppressions.json
+ policheck:
+ enabled: true
+ exclusionsFile: $(Build.SourcesDirectory)\scripts\guardian\PoliCheckExclusions.xml
+ spotBugs:
+ enabled: false
+ suppression:
+ suppressionFile: $(Build.SourcesDirectory)\scripts\guardian\source.gdnsuppress
+ tsa:
+ enabled: true
+ configFile: $(Build.SourcesDirectory)\scripts\guardian\tsaoptions-v2.json
+ use1ESPipelineTemplates: true
+ buildAgentHost: ${{ parameters.buildAgentHost }}
+ buildAgentWindows: ${{ parameters.buildAgentWindows }}
+ buildAgentWindowsNative: ${{ parameters.buildAgentWindows }}
+ buildAgentMac: ${{ parameters.buildAgentMac }}
+ buildAgentMacNative: ${{ parameters.buildAgentMac }}
+ buildAgentLinux: ${{ parameters.buildAgentLinux }}
+ buildAgentLinuxNative: ${{ parameters.buildAgentLinux }}
\ No newline at end of file
diff --git a/scripts/azure-template.yml b/scripts/azure-template.yml
new file mode 100644
index 0000000000..e7c203aa64
--- /dev/null
+++ b/scripts/azure-template.yml
@@ -0,0 +1,31 @@
+parameters:
+ - name: stages
+ type: stageList
+ default: []
+ - name: pool
+ type: object
+ default: {}
+ - name: customBuildTags
+ type: object
+ default: null
+
+stages:
+ - ${{ each stage in parameters.stages }}:
+ - ${{ each stageProperty in stage }}:
+ ${{ if notIn(stageProperty.key, 'jobs', 'pool') }}:
+ ${{ stageProperty.key }}: ${{ stageProperty.value }}
+ pool: ${{ parameters.pool }}
+ jobs:
+ - ${{ each job in stage.jobs }}:
+ - ${{ each jobProperty in job }}:
+ ${{ if notIn(jobProperty.key, 'steps', 'templateContext') }}:
+ ${{ jobProperty.key }}: ${{ jobProperty.value }}
+ steps:
+ - ${{ job.steps }}
+ - ${{ each output in job.templateContext.outputs }}:
+ - task: PublishPipelineArtifact@1
+ displayName: ${{ output.displayName }}
+ condition: ${{ coalesce(output.condition, 'succeeded()') }}
+ inputs:
+ artifactName: ${{ output.artifactName }}
+ targetPath: ${{ output.targetPath }}
\ No newline at end of file
diff --git a/scripts/azure-templates-bootstrapper.yml b/scripts/azure-templates-bootstrapper.yml
index ab003209e0..5fe77fc96b 100644
--- a/scripts/azure-templates-bootstrapper.yml
+++ b/scripts/azure-templates-bootstrapper.yml
@@ -1,7 +1,7 @@
parameters:
name: '' # in the form type_platform_host
displayName: '' # the human name
- vmImage: '' # the VM image
+ buildAgent: '' # the configuration for the build agent
packages: '' # any additional packages
target: '' # the bootstrapper target
dependsOn: [] # the dependiencies
@@ -30,26 +30,56 @@ parameters:
installLlvm: true # whether or not to install the LLVM compiler
installEmsdk: false # whether or not to install the Emscripten SDK
installNinja: false # whether or not to install the ninja build system
- artifactName: '' # the name of the artifact to merge this run into
+ publishArtifacts: [] # the additional artifacts to publish
tools: [] # any additional .net global tools
+ skipInstall: false # whether or not to install any tools
+ skipSteps: false # whether or not to run any steps
+ use1ESPipelineTemplates: false # whether or not we are building using the internal 1ES Pipeline Templates
+ sdl: [] # the SDL properties to use for this job
jobs:
- job: ${{ parameters.name }}
displayName: ${{ parameters.displayName }}
timeoutInMinutes: 180
- pool: ${{ parameters.vmImage.pool }}
+ pool: ${{ parameters.buildAgent.pool }}
dependsOn: ${{ parameters.dependsOn }}
condition: ${{ parameters.condition }}
variables:
- ${{ if ne(parameters.vmImage.variables, '') }}:
- ${{ parameters.vmImage.variables }}
+ ${{ if ne(parameters.buildAgent.variables, '') }}:
+ ${{ parameters.buildAgent.variables }}
${{ if ne(length(parameters.variables), 0) }}:
${{ parameters.variables }}
+ templateContext:
+ sdl: ${{ parameters.sdl }}
+ outputParentDirectory: 'output'
+ outputs:
+ - ${{ if eq(parameters.shouldPublish, 'true') }}:
+ - output: pipelineArtifact
+ displayName: 'Publish the ${{ parameters.name }} artifacts'
+ artifactName: ${{ parameters.name }}
+ targetPath: 'output'
+ - output: pipelineArtifact
+ displayName: 'Publish the failed ${{ parameters.name }} artifacts'
+ condition: failed()
+ artifactName: ${{ parameters.name }}_failed_$(System.JobAttempt)
+ targetPath: 'output'
+ - ${{ each additionalArtifact in parameters.publishArtifacts }}:
+ - output: pipelineArtifact
+ displayName: 'Publish the ${{ additionalArtifact.name }} artifacts'
+ artifactName: ${{ additionalArtifact.name }}
+ targetPath: ${{ additionalArtifact.path }}
+ - ${{ if eq(additionalArtifact.always, 'true') }}:
+ - output: pipelineArtifact
+ displayName: 'Publish the failed ${{ additionalArtifact.name }} artifacts'
+ condition: failed()
+ artifactName: ${{ additionalArtifact.name }}_failed_$(System.JobAttempt)
+ targetPath: ${{ additionalArtifact.path }}
+
steps:
# prepare
- checkout: self
submodules: recursive
- - template: azure-templates-variables.yml
+ - template: /scripts/azure-templates-variables.yml@self
# checkout required skia PR
- pwsh: .\scripts\checkout-skia.ps1 -GitHubToken $(GitHub.Token.PublicAccess)
@@ -57,7 +87,7 @@ jobs:
condition: eq(variables['Build.Reason'], 'PullRequest')
- ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
parameters:
state: 'pending'
@@ -66,13 +96,13 @@ jobs:
displayName: Determine build type
# provisioning steps
- - ${{ if ne(parameters.vmImage.provisioningSteps, '') }}:
- - ${{ parameters.vmImage.provisioningSteps }}
+ - ${{ if ne(parameters.buildAgent.provisioningSteps, '') }}:
+ - ${{ parameters.buildAgent.provisioningSteps }}
- ${{ if ne(length(parameters.provisioningSteps), 0) }}:
- ${{ parameters.provisioningSteps }}
# install any packages on linux
- - ${{ if and(eq(parameters.docker, ''), endsWith(parameters.name, '_linux')) }}:
+ - ${{ if and(eq(parameters.docker, ''), endsWith(parameters.name, '_linux'), ne(parameters.skipInstall, 'true')) }}:
- bash: |
sudo apt update
sudo apt install -y ${{ parameters.packages }}
@@ -81,7 +111,7 @@ jobs:
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''), ne('${{ parameters.packages }}', ''))
# install extra bits for the native builds
- - ${{ if startsWith(parameters.name, 'native_') }}:
+ - ${{ if and(startsWith(parameters.name, 'native_'), ne(parameters.skipInstall, 'true')) }}:
# switch to the correct Python version
- task: UsePythonVersion@0
displayName: Switch to the correct Python version
@@ -120,7 +150,7 @@ jobs:
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# install extra bits for the managed builds
- - ${{ if not(startsWith(parameters.name, 'native_')) }}:
+ - ${{ if and(not(startsWith(parameters.name, 'native_')), ne(parameters.skipInstall, 'true')) }}:
# install ninja
- ${{ if eq(parameters.installNinja, 'true') }}:
- pwsh: .\scripts\install-ninja.ps1
@@ -158,13 +188,6 @@ jobs:
- pwsh: Remove-Item "$env:AGENT_TOOLSDIRECTORY/dotnet" -Recurse -Force -ErrorAction SilentlyContinue
displayName: Cleanup existing versions of .NET
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- - task: UseDotNet@2
- condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- inputs:
- packageType: 'sdk'
- version: 3.1.x
- retryCountOnTaskFailure: 3
- displayName: Install .NET 3.1.x
- task: UseDotNet@2
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
inputs:
@@ -201,7 +224,7 @@ jobs:
displayName: Install the .NET workloads
# install the mac tools
- - ${{ if endsWith(parameters.name, '_macos') }}:
+ - ${{ if and(endsWith(parameters.name, '_macos'), ne(parameters.skipInstall, 'true')) }}:
- ${{ if not(startsWith(parameters.name, 'native_')) }}:
- bash: sudo ./scripts/select-xcode.sh $(XCODE_VERSION)
displayName: Switch to the latest Xcode
@@ -212,14 +235,14 @@ jobs:
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# install the linux tools
- - ${{ if and(eq(parameters.installEmsdk, 'true'), endsWith(parameters.name, '_linux')) }}:
+ - ${{ if and(eq(parameters.installEmsdk, 'true'), endsWith(parameters.name, '_linux'), ne(parameters.skipInstall, 'true')) }}:
- bash: ./scripts/install-emsdk.sh $(EMSCRIPTEN_VERSION)
displayName: Install the Emscripten SDK
retryCountOnTaskFailure: 3
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# install the Windows tools
- - ${{ if endsWith(parameters.name, '_windows') }}:
+ - ${{ if and(endsWith(parameters.name, '_windows'), ne(parameters.skipInstall, 'true')) }}:
# select the correct/latest version of Visual Studio
- pwsh: .\scripts\select-vs.ps1
displayName: Select Visual Studio
@@ -245,18 +268,19 @@ jobs:
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# install any .NET global tools
- - ${{ each tool in parameters.tools }}:
- - pwsh: dotnet tool install -g ${{ tool }}
- displayName: Install ${{ tool }}
- retryCountOnTaskFailure: 3
- condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if ne(parameters.skipInstall, 'true') }}:
+ - ${{ each tool in parameters.tools }}:
+ - pwsh: dotnet tool install -g ${{ tool }}
+ displayName: Install ${{ tool }}
+ retryCountOnTaskFailure: 3
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# download artifacts
- - template: azure-templates-download-artifacts.yml
+ - template: /scripts/azure-templates-download-artifacts.yml@self
parameters:
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
artifacts: ${{ parameters.requiredArtifacts }}
- - template: azure-templates-download-artifacts.yml
+ - template: /scripts/azure-templates-download-artifacts.yml@self
parameters:
condition: and(succeeded(), ne(variables['DOWNLOAD_EXTERNALS'], ''))
sourceBuildId: $(DOWNLOAD_EXTERNALS)
@@ -264,88 +288,76 @@ jobs:
- name: ${{ parameters.name }}
# pre-build steps
- - ${{ if ne(parameters.vmImage.preBuildSteps, '') }}:
- - ${{ parameters.vmImage.preBuildSteps }}
+ - ${{ if ne(parameters.buildAgent.preBuildSteps, '') }}:
+ - ${{ parameters.buildAgent.preBuildSteps }}
- ${{ if ne(length(parameters.preBuildSteps), 0) }}:
- ${{ parameters.preBuildSteps }}
- # build
- - ${{ if eq(parameters.docker, '') }}:
- - ${{ if endsWith(parameters.name, '_windows') }}:
- - pwsh: |
- Get-Content $PSCommandPath
- dotnet tool restore
- ${{ parameters.initScript }}
- dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
+ # actual build
+ - ${{ if ne(parameters.skipSteps, 'true') }}:
+ - ${{ if eq(parameters.docker, '') }}:
+ - ${{ if endsWith(parameters.name, '_windows') }}:
+ - pwsh: |
+ Get-Content $PSCommandPath
+ dotnet tool restore
+ ${{ parameters.initScript }}
+ dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
- env:
- JavaSdkDirectory: $(JAVA_HOME)
- LLVM_HOME: $(LLVM_HOME)
- # There seems to be a bug in some verions of mspdbcmf.exe. This looks to be fixed in a VS preview.
- AppxSymbolPackageEnabled: false
- displayName: Run the bootstrapper for ${{ parameters.target }}
- retryCountOnTaskFailure: ${{ parameters.retryCount }}
+ env:
+ JavaSdkDirectory: $(JAVA_HOME)
+ LLVM_HOME: $(LLVM_HOME)
+ # There seems to be a bug in some verions of mspdbcmf.exe. This looks to be fixed in a VS preview.
+ AppxSymbolPackageEnabled: false
+ displayName: Run the bootstrapper for ${{ parameters.target }}
+ retryCountOnTaskFailure: ${{ parameters.retryCount }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if not(endsWith(parameters.name, '_windows')) }}:
+ - bash: |
+ cat ${BASH_SOURCE[0]}
+ dotnet tool restore
+ ${{ parameters.initScript }}
+ dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
+
+ env:
+ JavaSdkDirectory: $(JAVA_HOME)
+ displayName: Run the bootstrapper for ${{ parameters.target }}
+ retryCountOnTaskFailure: ${{ parameters.retryCount }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ - ${{ if ne(parameters.docker, '') }}:
+ - ${{ if eq(parameters.use1ESPipelineTemplates, 'true') }}:
+ - task: 1ES.BuildContainerImage@1
+ displayName: Build the Docker image for ${{ parameters.docker }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ dockerfile: ${{ parameters.docker }}/Dockerfile
+ context: ${{ parameters.docker }}
+ image: skiasharp:skiasharp
+ buildArguments: --tag skiasharp ${{ parameters.dockerArgs }}
+ enableNetwork: true
+ - ${{ if ne(parameters.use1ESPipelineTemplates, 'true') }}:
+ - task: Docker@2
+ displayName: Build the Docker image for ${{ parameters.docker }}
+ condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
+ inputs:
+ command: build
+ buildContext: ${{ parameters.docker }}
+ dockerfile: ${{ parameters.docker }}/Dockerfile
+ arguments: --tag skiasharp ${{ parameters.dockerArgs }}
+ - bash: |
+ echo dotnet tool restore > cmd.sh
+ echo dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }} >> cmd.sh
+ sed -i 's/--gnArgs=\" \"//' cmd.sh
+ cat cmd.sh
+ displayName: Generate the script for the Docker image
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- - ${{ if not(endsWith(parameters.name, '_windows')) }}:
- bash: |
- cat ${BASH_SOURCE[0]}
- dotnet tool restore
- ${{ parameters.initScript }}
- dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }}
-
- env:
- JavaSdkDirectory: $(JAVA_HOME)
- displayName: Run the bootstrapper for ${{ parameters.target }}
+ docker run --rm --name skiasharp --volume $(pwd):/work skiasharp /bin/bash /work/cmd.sh
+ displayName: Run the bootstrapper for ${{ parameters.target }} using the Docker image
retryCountOnTaskFailure: ${{ parameters.retryCount }}
condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- - ${{ if ne(parameters.docker, '') }}:
- - task: Docker@2
- displayName: Build the Docker image for ${{ parameters.docker }}
- condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- inputs:
- command: build
- buildContext: ${{ parameters.docker }}
- dockerfile: ${{ parameters.docker }}/Dockerfile
- arguments: --tag skiasharp ${{ parameters.dockerArgs }}
- - bash: |
- echo dotnet tool restore > cmd.sh
- echo dotnet cake --target=${{ parameters.target }} --verbosity=${{ parameters.verbosity }} --configuration=${{ coalesce(parameters.configuration, 'Release') }} ${{ parameters.additionalArgs }} >> cmd.sh
- sed -i 's/--gnArgs=\" \"//' cmd.sh
- cat cmd.sh
- displayName: Generate the script for the Docker image
- condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
- - bash: |
- docker run --rm --name skiasharp --volume $(pwd):/work skiasharp /bin/bash /work/cmd.sh
- displayName: Run the bootstrapper for ${{ parameters.target }} using the Docker image
- retryCountOnTaskFailure: ${{ parameters.retryCount }}
- condition: and(succeeded(), eq(variables['DOWNLOAD_EXTERNALS'], ''))
# post-build steps
- ${{ parameters.postBuildSteps }}
- # publish artifacts
- - task: PublishBuildArtifacts@1
- displayName: Publish the ${{ parameters.name }} artifacts
- condition: or(${{ parameters.shouldPublish }}, failed())
- retryCountOnTaskFailure: 3
- inputs:
- artifactName: ${{ parameters.name }}
- pathToPublish: 'output'
- - ${{ if ne(parameters.artifactName, '') }}:
- - task: PublishBuildArtifacts@1
- displayName: Publish the combined ${{ parameters.artifactName }} artifacts
- retryCountOnTaskFailure: 3
- inputs:
- artifactName: ${{ parameters.artifactName }}
- pathToPublish: 'output'
- - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
- - task: ComponentGovernanceComponentDetection@0
- displayName: Run component detection
- condition: always()
- inputs:
- scanType: 'Register'
- verbosity: 'Verbose'
- alertWarningLevel: 'High'
-
- ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
diff --git a/scripts/azure-templates-download-artifacts.yml b/scripts/azure-templates-download-artifacts.yml
index db94dadcbe..2300409591 100644
--- a/scripts/azure-templates-download-artifacts.yml
+++ b/scripts/azure-templates-download-artifacts.yml
@@ -54,9 +54,10 @@ steps:
downloadType: 'single'
allowPartiallySucceededBuilds: true
artifactName: ${{ artifact.name }}
- downloadPath: 'download-temp'
+ downloadPath: 'download-temp/${{ artifact.name }}'
- pwsh: |
+ Get-ChildItem '.\download-temp\'
New-Item '.\output\${{ artifact.dir }}\' -Type Directory -Force | Out-Null
Get-ChildItem '.\download-temp\${{ artifact.name }}\' | Copy-Item -Destination '.\output\${{ artifact.dir }}\' -Recurse -Force
Remove-Item '.\download-temp\${{ artifact.name }}\' -Recurse -Force
diff --git a/scripts/azure-templates-linux-matrix.yml b/scripts/azure-templates-linux-matrix.yml
index 6bad3fbbd1..26681ce2d0 100644
--- a/scripts/azure-templates-linux-matrix.yml
+++ b/scripts/azure-templates-linux-matrix.yml
@@ -1,8 +1,9 @@
parameters:
- artifactName: '' # the name of the artifact to merge this run into
buildExternals: '' # the build number to download externals from
buildPipelineType: 'both' # the type of build pipeline setup
- vmImage: '' # the VM image
+ buildAgent: '' # the configuration for the build agent
+ use1ESPipelineTemplates: false # whether or not we are building using the internal 1ES Pipeline Templates
+ sdl: [] # the SDL properties to use for this job
builds:
- name: ''
desc: ''
@@ -20,15 +21,16 @@ parameters:
jobs:
- ${{ each build in parameters.builds }}:
- ${{ each item in parameters.matrix }}:
- - template: azure-templates-bootstrapper.yml
+ - template: /scripts/azure-templates-bootstrapper.yml@self
parameters:
name: ${{ replace(replace(format('native_linux_{0}_{1}_{2}_{3}_linux', item.arch, item.variant, build.name, item.alt), '__', '_'), '__', '_') }}
displayName: Linux ${{ replace(replace(replace(replace(replace(format('({0}|{1}|{2}|{3})', item.arch, item.variant, build.name, item.alt), '||', '|'), '||', '|'), '(|', '('), '|)', ')'), '|', ', ') }}
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.vmImage }}
+ buildAgent: ${{ parameters.buildAgent }}
+ use1ESPipelineTemplates: ${{ parameters.use1ESPipelineTemplates }}
docker: ${{ item.docker }}
dockerArgs: ${{ item.dockerArgs }}
target: ${{ coalesce(item.target, 'externals-linux') }}
- additionalArgs: --buildarch=${{ item.arch }} --variant=${{ coalesce(item.variant, 'linux') }}${{ build.name }} --gnArgs="\"${{ build.gnArgs }} ${{ item.gnArgs }}\"" ${{ build.additionalArgs }} ${{ item.additionalArgs }}
- artifactName: ${{ parameters.artifactName }}
+ additionalArgs: --buildarch=${{ item.arch }} --variant=${{ coalesce(item.variant, 'linux') }}${{ build.name }} --gnArgs="\"${{ build.gnArgs }} ${{ item.gnArgs }}\"" ${{ build.additionalArgs }} ${{ item.additionalArgs }}
\ No newline at end of file
diff --git a/scripts/azure-templates-merger.yml b/scripts/azure-templates-merger.yml
new file mode 100644
index 0000000000..23b9eb65c2
--- /dev/null
+++ b/scripts/azure-templates-merger.yml
@@ -0,0 +1,51 @@
+parameters:
+ name: '' # in the form type_platform_host
+ displayName: '' # the human name
+ buildAgent: '' # the configuration for the build agent
+ buildPipelineType: 'both' # the type of build pipeline setup
+ requiredArtifacts: [] # the artifacts that this build needs to download
+ matrixArtifacts: [] # the artifacts that this build needs to download
+ sdl: [] # the SDL properties to use for this job
+
+jobs:
+ - template: /scripts/azure-templates-bootstrapper.yml@self
+ parameters:
+ name: ${{ parameters.name }}
+ displayName: ${{ parameters.displayName }}
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgent }}
+ skipInstall: true
+ skipSteps: true
+ requiredArtifacts: ${{ parameters.requiredArtifacts }}
+ preBuildSteps:
+ - pwsh: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject) --use-git-aliases true
+ displayName: Configure the az CLI tool
+ - ${{ each artifact in parameters.matrixArtifacts }}:
+ - pwsh: |
+ $artifactJson=@'
+ ${{ artifact.jobs }}
+ '@
+
+ echo $artifactJson
+
+ $json = ConvertFrom-Json $artifactJson
+ $objects = $json | Get-Member -MemberType NoteProperty
+ $names = $objects | ForEach-Object { $json."$($_.Name)".name }
+
+ Write-Host "Found $($names.Length) items:"
+ $names | ForEach-Object { Write-Host " - $_" }
+
+ $dir = "$(Build.SourcesDirectory)/output"
+ New-Item "$dir" -Type Directory -Force | Out-Null
+
+ $id = "$(Build.BuildId)"
+ foreach ($name in $names) {
+ Write-Host "Downloading '$name'..."
+ az pipelines runs artifact download --artifact-name "$name" --path "$dir" --run-id "$id" --verbose
+ }
+ Write-Host "Downloads complete."
+ Get-ChildItem "$dir"
+ env:
+ AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
+ displayName: Download the pre-built ${{ artifact.name }} artifacts
diff --git a/scripts/azure-templates-stages.yml b/scripts/azure-templates-stages.yml
index 3095f48a26..ebf702e81c 100644
--- a/scripts/azure-templates-stages.yml
+++ b/scripts/azure-templates-stages.yml
@@ -5,21 +5,33 @@ parameters:
- name: buildExternals
type: string
default: 'latest'
- - name: VM_IMAGE_HOST
+ - name: buildAgentHost
type: object
- - name: VM_IMAGE_WINDOWS
+ - name: buildAgentWindows
type: object
- - name: VM_IMAGE_WINDOWS_NATIVE
+ - name: buildAgentWindowsNative
type: object
- - name: VM_IMAGE_MAC
+ - name: buildAgentMac
type: object
- - name: VM_IMAGE_MAC_NATIVE
+ - name: buildAgentMacNative
type: object
- - name: VM_IMAGE_LINUX
+ - name: buildAgentLinux
type: object
- - name: VM_IMAGE_LINUX_NATIVE
+ - name: buildAgentLinuxNative
type: object
- - name: runCompliance
+ - name: sdl
+ type: object
+ default:
+ apiscan:
+ enabled: false
+ binskim:
+ break: false
+ spotBugs:
+ enabled: false
+ - name: use1ESPipelineTemplates
+ type: boolean
+ default: false
+ - name: enableSigning
type: boolean
default: false
@@ -29,200 +41,268 @@ stages:
jobs:
- job: prepare # Prepare Build
displayName: Prepare Build
- pool: ${{ parameters.VM_IMAGE_HOST.pool }}
+ pool: ${{ parameters.buildAgentHost.pool }}
steps:
- checkout: none
- - template: azure-templates-variables.yml
+ - template: /scripts/azure-templates-variables.yml@self
parameters:
updateBuild: true
- ${{ if eq(parameters.buildPipelineType, 'build') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
parameters:
context: 'SkiaSharp-Tests'
state: 'pending'
displayName: Queue up the status for the tests pipeline
- ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
- stage: native_windows
displayName: Native Windows
dependsOn: prepare
jobs:
- - template: azure-templates-bootstrapper.yml # Build Native Android|x86 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|x86 (Win)
parameters:
name: native_android_x86_windows
displayName: Android x86
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-android
additionalArgs: --buildarch=x86
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Android|x64 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|x64 (Win)
parameters:
name: native_android_x64_windows
displayName: Android x64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-android
additionalArgs: --buildarch=x64
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Android|arm (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|arm (Win)
parameters:
name: native_android_arm_windows
displayName: Android arm
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-android
additionalArgs: --buildarch=arm
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Android|arm64 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|arm64 (Win)
parameters:
name: native_android_arm64_windows
displayName: Android arm64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-android
additionalArgs: --buildarch=arm64
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Tizen (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Tizen (Win)
parameters:
name: native_tizen_windows
displayName: Tizen
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-tizen
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Win32|x86 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|x86 (Win)
parameters:
name: native_win32_x86_windows
displayName: Win32 x86
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-windows
additionalArgs: --buildarch=x86
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Win32|x64 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|x64 (Win)
parameters:
name: native_win32_x64_windows
displayName: Win32 x64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-windows
additionalArgs: --buildarch=x64
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Win32|arm64 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|arm64 (Win)
parameters:
name: native_win32_arm64_windows
displayName: Win32 arm64
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-windows
+ additionalArgs: --buildarch=arm64
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|x86 (Win + MSVC)
+ parameters:
+ name: native_win32_x86_msvc_windows
+ displayName: Win32 x86 [MSVC]
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-windows
+ additionalArgs: --buildarch=x86 --llvm="msvc"
+ installLlvm: false
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|x64 (Win + MSVC)
+ parameters:
+ name: native_win32_x64_msvc_windows
+ displayName: Win32 x64 [MSVC]
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-windows
+ additionalArgs: --buildarch=x64 --llvm="msvc"
+ installLlvm: false
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Win32|arm64 (Win + MSVC)
+ parameters:
+ name: native_win32_arm64_msvc_windows
+ displayName: Win32 arm64 [MSVC]
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-windows
+ additionalArgs: --buildarch=arm64 --llvm="msvc"
+ installLlvm: false
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|x86 (Win)
+ parameters:
+ name: native_winui_x86_windows
+ displayName: WinUI x86
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-winui
+ additionalArgs: --buildarch=x86
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|x64 (Win)
+ parameters:
+ name: native_winui_x64_windows
+ displayName: WinUI x64
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-winui
+ additionalArgs: --buildarch=x64
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native WinUI|arm64 (Win)
+ parameters:
+ name: native_winui_arm64_windows
+ displayName: WinUI arm64
+ sdl: ${{ parameters.sdl }}
+ buildExternals: ${{ parameters.buildExternals }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
+ target: externals-winui
additionalArgs: --buildarch=arm64
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native NanoServer|x64 (Win)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native NanoServer|x64 (Win)
parameters:
name: native_win32_x64_nanoserver_windows
displayName: Nano Server x64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentWindowsNative }}
target: externals-nanoserver
additionalArgs: --buildarch=x64
- artifactName: native
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
- stage: native_macos
displayName: Native macOS
dependsOn: prepare
jobs:
- - template: azure-templates-bootstrapper.yml # Build Native Android|x86 (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|x86 (macOS)
parameters:
name: native_android_x86_macos
displayName: Android x86
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-android
additionalArgs: --buildarch=x86
- - template: azure-templates-bootstrapper.yml # Build Native Android|x64 (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|x64 (macOS)
parameters:
name: native_android_x64_macos
displayName: Android x64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-android
additionalArgs: --buildarch=x64
- - template: azure-templates-bootstrapper.yml # Build Native Android|arm (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|arm (macOS)
parameters:
name: native_android_arm_macos
displayName: Android arm
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-android
additionalArgs: --buildarch=arm
- - template: azure-templates-bootstrapper.yml # Build Native Android|arm64 (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Android|arm64 (macOS)
parameters:
name: native_android_arm64_macos
displayName: Android arm64
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-android
additionalArgs: --buildarch=arm64
- - template: azure-templates-bootstrapper.yml # Build Native iOS (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native iOS (macOS)
parameters:
name: native_ios_macos
displayName: iOS
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-ios
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Mac Catalyst (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Mac Catalyst (macOS)
parameters:
name: native_maccatalyst_macos
displayName: Mac Catalyst
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-maccatalyst
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native macOS (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native macOS (macOS)
parameters:
name: native_macos_macos
displayName: macOS
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-macos
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native tvOS (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native tvOS (macOS)
parameters:
name: native_tvos_macos
displayName: tvOS
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-tvos
- artifactName: native
- - template: azure-templates-bootstrapper.yml # Build Native Tizen (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Tizen (macOS)
parameters:
name: native_tizen_macos
displayName: Tizen
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentMacNative }}
target: externals-tizen
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
@@ -230,12 +310,13 @@ stages:
displayName: Native Linux
dependsOn: prepare
jobs:
- - template: azure-templates-linux-matrix.yml # Build Native Linux (Linux)
+ - template: /scripts/azure-templates-linux-matrix.yml@self # Build Native Linux (Linux)
parameters:
- artifactName: native
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentLinuxNative }}
+ use1ESPipelineTemplates: ${{ parameters.use1ESPipelineTemplates }}
builds:
- name: ''
- name: nodeps
@@ -255,13 +336,13 @@ stages:
docker: scripts/Docker/debian9/clang-cross
dockerArgs: --build-arg TOOLCHAIN_ARCH=aarch64-linux-gnu --build-arg TOOLCHAIN_ARCH_SHORT=arm64
target: externals-linux-clang-cross
- - template: azure-templates-bootstrapper.yml # Build Native Tizen (Linux)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Native Tizen (Linux)
parameters:
name: native_tizen_linux
displayName: Tizen
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX_NATIVE }}
+ buildAgent: ${{ parameters.buildAgentLinuxNative }}
packages: $(TIZEN_LINUX_PACKAGES)
target: externals-tizen
@@ -270,12 +351,13 @@ stages:
displayName: Native WASM
dependsOn: prepare
jobs:
- - template: azure-templates-wasm-matrix.yml # Build Native WASM (Linux)
+ - template: /scripts/azure-templates-wasm-matrix.yml@self # Build Native WASM (Linux)
parameters:
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX_NATIVE }}
- artifactName: native
+ buildAgent: ${{ parameters.buildAgentLinuxNative }}
+ use1ESPipelineTemplates: ${{ parameters.use1ESPipelineTemplates }}
emscripten:
- 2.0.6:
displayName: 2.0.6
@@ -329,54 +411,131 @@ stages:
features: _wasmeh,simd,mt
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
- - stage: managed
- displayName: Build Managed
+ - stage: native
+ displayName: Native
+ variables:
+ nativeLinuxJobs: $[ convertToJson(stageDependencies.native_linux) ]
+ nativeWasmJobs: $[ convertToJson(stageDependencies.native_wasm) ]
dependsOn:
- native_windows
- native_macos
- native_linux
- native_wasm
jobs:
- - template: azure-templates-bootstrapper.yml # Build Managed (Windows)
+ - template: /scripts/azure-templates-merger.yml@self # Merge Native Artifacts
+ parameters:
+ name: native
+ displayName: Merge Native Artifacts
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentHost }}
+ requiredArtifacts:
+ # Android
+ - name: native_android_x86_windows
+ - name: native_android_x64_windows
+ - name: native_android_arm_windows
+ - name: native_android_arm64_windows
+ # Tizen
+ - name: native_tizen_windows
+ # Win32
+ - name: native_win32_x86_windows
+ - name: native_win32_x64_windows
+ - name: native_win32_arm64_windows
+ # WinUI
+ - name: native_winui_x86_windows
+ - name: native_winui_x64_windows
+ - name: native_winui_arm64_windows
+ # Nano Server
+ - name: native_win32_x64_nanoserver_windows
+ # iOS
+ - name: native_ios_macos
+ # Mac Catalyst
+ - name: native_maccatalyst_macos
+ # macOS
+ - name: native_macos_macos
+ # tvOS
+ - name: native_tvos_macos
+ matrixArtifacts:
+ - name: native_linux
+ jobs: $(nativeLinuxJobs)
+ - name: native_wasm
+ jobs: $(nativeWasmJobs)
+ - template: /scripts/azure-templates-merger.yml@self # Merge Native WASM Artifacts
+ parameters:
+ name: native_wasm
+ displayName: Merge Native WASM Artifacts
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentHost }}
+ matrixArtifacts:
+ - name: native_wasm
+ jobs: $(nativeWasmJobs)
+ - template: /scripts/azure-templates-merger.yml@self # Merge Native MSVC Artifacts
+ parameters:
+ name: native_msvc
+ displayName: Merge Native MSVC Artifacts
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentHost }}
+ requiredArtifacts:
+ - name: native_win32_x86_msvc_windows
+ - name: native_win32_x64_msvc_windows
+ - name: native_win32_arm64_msvc_windows
+
+ - ${{ if ne(parameters.buildPipelineType, 'build') }}:
+ - stage: managed
+ displayName: Build Managed
+ ${{ if eq(parameters.buildPipelineType, 'tests') }}:
+ dependsOn: prepare
+ ${{ if eq(parameters.buildPipelineType, 'both') }}:
+ dependsOn: native
+ jobs:
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Validate Interop
+ parameters:
+ name: managed_interop_windows
+ displayName: Validate Interop
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindows}}
+ target: externals-interop
+ additionalArgs: --skipExternals="all"
+ installAndroidSdk: false
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Managed (Windows)
parameters:
name: managed_windows
displayName: Managed (Windows)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ buildAgent: ${{ parameters.buildAgentWindows}}
target: libs
additionalArgs: --skipExternals="all"
requiredArtifacts:
- name: native
- artifactName: managed
postBuildSteps:
- pwsh: Remove-Item ./output/native/ -Recurse -Force -ErrorAction Continue
displayName: Delete the native folder
- - template: azure-templates-bootstrapper.yml # Build Managed (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Managed (macOS)
parameters:
name: managed_macos
displayName: Managed (macOS)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: libs
additionalArgs: --skipExternals="all"
requiredArtifacts:
- name: native
- artifactName: managed
postBuildSteps:
- pwsh: Remove-Item ./output/native/ -Recurse -Force -ErrorAction Continue
displayName: Delete the native folder
- - template: azure-templates-bootstrapper.yml # Build Managed (Linux)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Managed (Linux)
parameters:
name: managed_linux
displayName: Managed (Linux)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX }}
+ buildAgent: ${{ parameters.buildAgentLinux }}
packages: $(MANAGED_LINUX_PACKAGES)
target: libs
additionalArgs: --skipExternals="all"
requiredArtifacts:
- name: native
- artifactName: managed
postBuildSteps:
- pwsh: Remove-Item ./output/native/ -Recurse -Force -ErrorAction Continue
displayName: Delete the native folder
@@ -384,49 +543,86 @@ stages:
- ${{ if ne(parameters.buildPipelineType, 'tests') }}:
- stage: package
displayName: Package NuGets
- dependsOn:
- - native_windows
- - native_macos
- - native_linux
- - native_wasm
+ dependsOn: native
jobs:
- - template: azure-templates-bootstrapper.yml # Package NuGets
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Package NuGets
parameters:
- name: package_windows
+ name: package_normal_windows
displayName: Package NuGets
+ sdl: ${{ parameters.sdl }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
- target: nuget
+ buildAgent: ${{ parameters.buildAgentWindows}}
+ target: nuget-normal
additionalArgs: --skipExternals="all"
+ shouldPublish: false
requiredArtifacts:
- name: native
postBuildSteps:
- - task: PublishBuildArtifacts@1
- displayName: Publish the nuget artifacts
- inputs:
- artifactName: nuget
- pathToPublish: 'output/nugets'
- - task: PublishBuildArtifacts@1
- displayName: Publish the special nuget artifacts
- inputs:
- artifactName: nuget_special
- pathToPublish: 'output/nugets-special'
- - task: PublishBuildArtifacts@1
- displayName: Publish the special nuget artifacts
- inputs:
- artifactName: nuget_symbols
- pathToPublish: 'output/nugets-symbols'
- - task: PublishBuildArtifacts@1
- displayName: Publish the SignList.xml into nuget artifacts
- inputs:
- artifactName: nuget
- pathToPublish: 'scripts\SignList.xml'
- pwsh: |
- Remove-Item ./output/native/ -Recurse -Force
- Remove-Item ./output/nugets/ -Recurse -Force
- Remove-Item ./output/nugets-special/ -Recurse -Force
- Remove-Item ./output/nugets-symbols/ -Recurse -Force
- displayName: Delete the pre-published folders
+ Remove-Item ./output/native/ -Recurse -Force -ErrorAction Continue
+ Move-Item -Path '.\output\' -Destination '$(Build.ArtifactStagingDirectory)\output\'
+ New-Item '.\output\' -Type Directory -Force | Out-Null
+ displayName: Re-organize the output folder for publishing
+ - pwsh: |
+ Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\nugets\' -Destination '.\output\'
+ Copy-Item -Path '.\scripts\SignList.xml' -Destination '.\output\nugets\'
+ displayName: Prepare the nugets artifact for publishing
+ - pwsh: |
+ Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\nugets-symbols\' -Destination '.\output\'
+ displayName: Prepare the nugets-symbols artifact for publishing
+ - pwsh: |
+ Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\' -Destination '.\output\'
+ displayName: Prepare the build artifact for publishing
+ - pwsh: |
+ $nupkgs = (Get-ChildItem ".\output\nugets*\*.*nupkg")
+ foreach ($nupkg in $nupkgs) {
+ $filename = $nupkg.Name.TrimEnd('.nupkg')
+ $dest = ".\output\extracted_nugets\$filename"
+ Write-Host "Extracting '$nupkg' to '$dest'..."
+ Expand-Archive $nupkg $dest
+ }
+ displayName: Extract all the .nupkg files for scanning
+ publishArtifacts:
+ - name: package_normal_windows
+ path: '.\output\output\'
+ - name: nuget
+ path: '.\output\nugets'
+ - name: nuget_symbols
+ path: '.\output\nugets-symbols'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Package Special NuGets
+ parameters:
+ name: package_special_windows
+ displayName: Package Special NuGets
+ sdl: ${{ parameters.sdl }}
+ buildPipelineType: ${{ parameters.buildPipelineType }}
+ buildAgent: ${{ parameters.buildAgentWindows}}
+ dependsOn: package_normal_windows
+ target: nuget-special
+ additionalArgs: --skipExternals="all" --exclusive
+ shouldPublish: false
+ requiredArtifacts:
+ - name: nuget
+ dir: nugets
+ - name: nuget_symbols
+ dir: nugets-symbols
+ postBuildSteps:
+ - pwsh: |
+ Remove-Item ./output/nugets/ -Recurse -Force -ErrorAction Continue
+ Remove-Item ./output/nugets-symbols/ -Recurse -Force -ErrorAction Continue
+ Move-Item -Path '.\output\' -Destination '$(Build.ArtifactStagingDirectory)\output\'
+ New-Item '.\output\' -Type Directory -Force | Out-Null
+ displayName: Re-organize the output folder for publishing
+ - pwsh: |
+ Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\nugets-special\' -Destination '.\output\'
+ displayName: Prepare the nugets-special artifact for publishing
+ - pwsh: |
+ Move-Item -Path '$(Build.ArtifactStagingDirectory)\output\' -Destination '.\output\'
+ displayName: Prepare the build artifact for publishing
+ publishArtifacts:
+ - name: package_special_windows
+ path: '.\output\output\'
+ - name: nuget_special
+ path: '.\output\nugets-special'
- ${{ if ne(parameters.buildPipelineType, 'build') }}:
- stage: api_diff
@@ -436,37 +632,30 @@ stages:
${{ if eq(parameters.buildPipelineType, 'both') }}:
dependsOn: package
jobs:
- - template: azure-templates-bootstrapper.yml # API Diff
+ - template: /scripts/azure-templates-bootstrapper.yml@self # API Diff
parameters:
name: api_diff_windows
displayName: API Diff
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ buildAgent: ${{ parameters.buildAgentWindows}}
target: docs-api-diff
additionalArgs: --nugetDiffPrerelease=$(NUGET_DIFF_PRERELEASE)
shouldPublish: false
requiredArtifacts:
- - name: package_windows
- name: nuget
dir: nugets
preBuildSteps:
- pwsh: .\scripts\install-gtk.ps1
displayName: Install GTK# 2.12
- postBuildSteps:
- - task: PublishBuildArtifacts@1
- displayName: Publish the API diffs
- condition: always()
- inputs:
- artifactName: api-diff
- pathToPublish: '$(Build.SourcesDirectory)\output\api-diff'
- - task: PublishBuildArtifacts@1
- displayName: Publish the changelogs
- condition: always()
- inputs:
- artifactName: changelogs
- pathToPublish: '$(Build.SourcesDirectory)\changelogs'
+ publishArtifacts:
+ - name: api-diff
+ always: true
+ path: '$(Build.SourcesDirectory)\output\api-diff'
+ - name: changelogs
+ always: true
+ path: '$(Build.SourcesDirectory)\changelogs'
- - ${{ if and(eq(variables['System.TeamProject'], 'devdiv'), ne(parameters.buildPipelineType, 'tests'), ne(variables['System.PullRequest.IsFork'], 'true')) }}:
+ - ${{ if eq(parameters.enableSigning, 'true') }}:
- stage: signing
displayName: Sign NuGets
dependsOn: package
@@ -477,17 +666,8 @@ stages:
signType: 'Real'
${{ if not(or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'))) }}:
signType: 'Test'
-
- - ${{ if and(eq(variables['System.TeamProject'], 'devdiv'), ne(parameters.buildPipelineType, 'tests'), ne(variables['System.PullRequest.IsFork'], 'true')) }}:
- - stage: sbom
- displayName: 'Software Bill of Materials'
- dependsOn: signing
- jobs:
- - template: compliance/sbom/job.v1.yml@xamarin-templates # Software Bill of Materials (SBOM): https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/secure-supply-chain/ado-sbom-generator
- parameters:
- artifactNames: ['nuget']
- packageName: 'SkiaSharp'
- packageFilter: '*.nupkg'
+ use1ESTemplate: ${{ parameters.use1ESPipelineTemplates }}
+ usePipelineArtifactTasks: true
- ${{ if ne(parameters.buildPipelineType, 'build') }}:
- stage: tests
@@ -495,18 +675,14 @@ stages:
${{ if eq(parameters.buildPipelineType, 'tests') }}:
dependsOn: prepare
${{ if eq(parameters.buildPipelineType, 'both') }}:
- dependsOn:
- - native_windows
- - native_macos
- - native_linux
- - native_wasm
+ dependsOn: native
jobs:
- - template: azure-templates-bootstrapper.yml # Tests|netfx (Windows)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|netfx (Windows)
parameters:
name: tests_netfx_windows
displayName: Windows (.NET Framework)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ buildAgent: ${{ parameters.buildAgentWindows}}
target: tests-netfx
additionalArgs: --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
@@ -522,18 +698,16 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'Windows .NET Framework Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_netfx_windows
- pathToPublish: 'output/logs/testlogs'
- - template: azure-templates-bootstrapper.yml # Tests|netcore (Windows)
+ publishArtifacts:
+ - name: testlogs_netfx_windows
+ always: true
+ path: 'output/logs/testlogs'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|netcore (Windows)
parameters:
name: tests_netcore_windows
displayName: Windows (.NET Core)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ buildAgent: ${{ parameters.buildAgentWindows}}
target: tests-netcore
additionalArgs: --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
@@ -549,23 +723,18 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'Windows .NET Core Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_netcore_windows
- pathToPublish: 'output/logs/testlogs'
- - task: PublishBuildArtifacts@1
- displayName: 'Publish the code coverage results'
- inputs:
- artifactName: coverage_netcore_windows
- pathToPublish: 'output/coverage'
- - template: azure-templates-bootstrapper.yml # Tests|netcore (macOS)
+ publishArtifacts:
+ - name: testlogs_netcore_windows
+ always: true
+ path: 'output/logs/testlogs'
+ - name: coverage_netcore_windows
+ path: 'output/coverage'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|netcore (macOS)
parameters:
name: tests_netcore_macos
displayName: macOS (.NET Core)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: tests-netcore
additionalArgs: --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
@@ -579,23 +748,18 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'macOS .NET Core Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_netcore_macos
- pathToPublish: 'output/logs/testlogs'
- - task: PublishBuildArtifacts@1
- displayName: 'Publish the code coverage results'
- inputs:
- artifactName: coverage_netcore_macos
- pathToPublish: 'output/coverage'
- - template: azure-templates-bootstrapper.yml # Tests|netcore (Linux)
+ publishArtifacts:
+ - name: testlogs_netcore_macos
+ always: true
+ path: 'output/logs/testlogs'
+ - name: coverage_netcore_macos
+ path: 'output/coverage'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|netcore (Linux)
parameters:
name: tests_netcore_linux
displayName: Linux (.NET Core)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX }}
+ buildAgent: ${{ parameters.buildAgentLinux }}
packages: $(MANAGED_LINUX_PACKAGES)
target: tests-netcore
additionalArgs: --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
@@ -611,23 +775,18 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'Linux .NET Core Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_netcore_linux
- pathToPublish: 'output/logs/testlogs'
- - task: PublishBuildArtifacts@1
- displayName: 'Publish the code coverage results'
- inputs:
- artifactName: coverage_netcore_linux
- pathToPublish: 'output/coverage'
- - template: azure-templates-bootstrapper.yml # Tests|android (macOS)
+ publishArtifacts:
+ - name: testlogs_netcore_linux
+ always: true
+ path: 'output/logs/testlogs'
+ - name: coverage_netcore_linux
+ path: 'output/coverage'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|android (macOS)
parameters:
name: tests_android_macos
displayName: Android (macOS)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: tests-android
additionalArgs: --device=android-emulator-64 --deviceVersion=$(ANDROID_TEST_DEVICE_VERSION) --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
@@ -649,25 +808,23 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'Android Tests (API $(ANDROID_TEST_DEVICE_VERSION))'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_android_$(ANDROID_TEST_DEVICE_VERSION)
- pathToPublish: 'output/logs/testlogs'
- - template: azure-templates-bootstrapper.yml # Tests|ios (macOS)
+ publishArtifacts:
+ - name: testlogs_android_$(ANDROID_TEST_DEVICE_VERSION)
+ always: true
+ path: 'output/logs/testlogs'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|ios (macOS)
parameters:
name: tests_ios_macos
displayName: iOS (macOS)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: tests-ios
additionalArgs: --device=ios-simulator-64 --deviceVersion=$(IOS_TEST_DEVICE_VERSION) --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
requiredArtifacts:
- name: native_ios_macos
preBuildSteps:
- - template: azure-templates-provisioning-profiles.yml
+ - template: /scripts/azure-templates-provisioning-profiles.yml@self
postBuildSteps:
- task: PublishTestResults@2
displayName: Publish the iOS test results
@@ -676,51 +833,47 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'iOS Tests (v$(IOS_TEST_DEVICE_VERSION))'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_ios_$(IOS_TEST_DEVICE_VERSION)
- pathToPublish: 'output/logs/testlogs'
- - template: azure-templates-bootstrapper.yml # Tests|maccatalyst (macOS)
+ publishArtifacts:
+ - name: testlogs_ios_$(IOS_TEST_DEVICE_VERSION)
+ always: true
+ path: 'output/logs/testlogs'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests|maccatalyst (macOS)
parameters:
name: tests_maccatalyst_macos
displayName: Mac Catalyst (macOS)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: tests-maccatalyst
additionalArgs: --device=maccatalyst --skipExternals="all" --coverage=$(ENABLE_CODE_COVERAGE)
shouldPublish: false
requiredArtifacts:
- name: native_maccatalyst_macos
preBuildSteps:
- - template: azure-templates-provisioning-profiles.yml
+ - template: /scripts/azure-templates-provisioning-profiles.yml@self
postBuildSteps:
- task: PublishTestResults@2
- displayName: Publish the iOMac CatalystS test results
+ displayName: Publish the Mac Catalyst test results
condition: always()
inputs:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/TestResults.xml'
testRunTitle: 'Mac Catalyst Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_maccatalyst
- pathToPublish: 'output/logs/testlogs'
- - template: azure-templates-bootstrapper.yml # Tests [WASM] (Linux)
+ publishArtifacts:
+ - name: testlogs_maccatalyst
+ always: true
+ path: 'output/logs/testlogs'
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Tests [WASM] (Linux)
parameters:
name: tests_wasm_linux
displayName: WASM (Linux)
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX }}
+ buildAgent: ${{ parameters.buildAgentLinux }}
packages: $(MANAGED_LINUX_PACKAGES) ninja-build
target: tests-wasm
additionalArgs: --skipExternals="all" --coverage=false --chromedriver=$(CHROMEWEBDRIVER)
shouldPublish: false
requiredArtifacts:
- - name: native_wasm_linux
+ - name: native_wasm
installEmsdk: true
initScript: source ~/emsdk/emsdk_env.sh
postBuildSteps:
@@ -731,27 +884,25 @@ stages:
testResultsFormat: xUnit
testResultsFiles: 'output/logs/testlogs/**/*.xml'
testRunTitle: 'Linux WASM Tests'
- - task: PublishBuildArtifacts@1
- displayName: Publish the test logs
- condition: always()
- inputs:
- artifactName: testlogs_wasm
- pathToPublish: 'output/logs/testlogs'
+ publishArtifacts:
+ - name: testlogs_wasm
+ always: true
+ path: 'output/logs/testlogs'
# TODO: add tests for linux alpine
# TODO: add tests for linux no dependencies
# TODO: add tests for windows nano server
- job: coverage_reports # Coverage Reports
displayName: Coverage Reports
- pool: ${{ parameters.VM_IMAGE_HOST.pool }}
+ pool: ${{ parameters.buildAgentHost.pool }}
dependsOn:
- tests_netcore_windows
- tests_netcore_macos
- tests_netcore_linux
steps:
- checkout: self
- - template: azure-templates-variables.yml
+ - template: /scripts/azure-templates-variables.yml@self
- ${{ if ne(parameters.buildPipelineType, 'both') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
parameters:
state: 'pending'
- task: DownloadBuildArtifacts@1
@@ -775,7 +926,7 @@ stages:
codeCoverageTool: Cobertura
summaryFileLocation: 'output/**/Cobertura.xml'
- ${{ if ne(parameters.buildPipelineType, 'both') }}:
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-github-status.yml@self
- ${{ if ne(parameters.buildPipelineType, 'build') }}:
- stage: samples
@@ -785,12 +936,12 @@ stages:
${{ if eq(parameters.buildPipelineType, 'both') }}:
dependsOn: package
jobs:
- - template: azure-templates-bootstrapper.yml # Build Samples (Windows)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Samples (Windows)
parameters:
name: samples_windows
displayName: Windows
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_WINDOWS}}
+ buildAgent: ${{ parameters.buildAgentWindows}}
target: samples
requiredArtifacts:
- name: nuget
@@ -798,12 +949,12 @@ stages:
postBuildSteps:
- pwsh: Remove-Item ./output/nugets/ -Recurse -Force -ErrorAction Continue
displayName: Delete the nugets folder
- - template: azure-templates-bootstrapper.yml # Build Samples (macOS)
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Samples (macOS)
parameters:
name: samples_macos
displayName: macOS
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_MAC }}
+ buildAgent: ${{ parameters.buildAgentMac }}
target: samples
installNinja: true
shouldPublish: false
@@ -811,13 +962,13 @@ stages:
- name: nuget
dir: nugets
preBuildSteps:
- - template: azure-templates-provisioning-profiles.yml
- - template: azure-templates-bootstrapper.yml # Build Samples (Linux)
+ - template: /scripts/azure-templates-provisioning-profiles.yml@self
+ - template: /scripts/azure-templates-bootstrapper.yml@self # Build Samples (Linux)
parameters:
name: samples_linux
displayName: Linux
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.VM_IMAGE_LINUX }}
+ buildAgent: ${{ parameters.buildAgentLinux }}
packages: $(MANAGED_LINUX_PACKAGES)
target: samples
shouldPublish: false
@@ -827,49 +978,61 @@ stages:
installEmsdk: true
initScript: source ~/emsdk/emsdk_env.sh
- - ${{ if and(eq(variables['System.TeamProject'], 'devdiv'), ne(parameters.buildPipelineType, 'tests'), ne(variables['System.PullRequest.IsFork'], 'true'), or(and(eq(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'))), parameters.runCompliance)) }}:
- - template: security/full/v1.yml@xamarin-templates
+ - ${{ if eq(parameters.sdl.apiscan.enabled, 'true') }}:
+ - template: security/apiscan/v0.yml@xamarin-templates
parameters:
+ windowsPoolName: ${{ parameters.buildAgentHost.pool.name }}
+ windowsImageOverride: ${{ parameters.buildAgentHost.pool.image }}
+ timeoutInMinutes: 480
stageDependsOn:
- - managed
- - native_windows
- - native_macos
- - native_linux
- - native_wasm
- complianceEnabled: true
- complianceTimeoutInMinutes: 480
+ - package
scanArtifacts:
- - managed
- - native
- antiMalwareEnabled: true
- binSkimEnabled: true
- policheckExclusionFile: $(Build.SourcesDirectory)\scripts\guardian\PoliCheckExclusions.xml
- policheckGdnSuppressionFilesFolder: $(Build.SourcesDirectory)\scripts\guardian
- credScanEnabled: true
- credScanSuppressionFile: $(Build.SourcesDirectory)\scripts\guardian\CredScanSuppressions.json
- sourceGdnSuppressionFile: $(Build.SourcesDirectory)\scripts\guardian\source.gdnsuppress
- tsaConfigFile: $(Build.SourcesDirectory)\scripts\guardian\tsaoptions-v2.json
- tsaReportBranch: $(Build.SourceBranch)
- enableCodeInspector: true
- apiScanEnabled: true
+ - nuget
+ - nuget_symbols
+ - native_msvc
apiScanSoftwareName: 'SkiaSharp'
- apiScanSoftwareVersionNum: $(Build.BuildNumber)
+ apiScanSoftwareVersionNum: $(SKIASHARP_MAJOR_VERSION)
+ apiScanPreserveLogsFolder: true
+ apiScanAuthConnectionString: 'runAs=App;AppId=$(ApiScanClientId)'
+ apiScanSurrogateConfigurationFolder: $(Build.ArtifactStagingDirectory)\APIScanSurrogates
+ preScanSteps:
+ - pwsh: |
+ $softwareFolder = "$(Build.ArtifactStagingDirectory)\binaries-to-scan"
+ $surrogateFile = "$(Build.SourcesDirectory)\scripts\guardian\APIScanSurrogates.in.xml"
+ $destFolder = "$(Build.ArtifactStagingDirectory)\APIScanSurrogates"
+ $destFile = "$destFolder\APIScanSurrogates.xml"
+ New-Item -ItemType Directory -Force -Path $destFolder | Out-Null
+ $surrogateContents = (Get-Content $surrogateFile)
+ $surrogateContents = $surrogateContents.Replace("{SOFTWARE_FOLDER}", $softwareFolder)
+ $surrogateContents | Set-Content $destFile
+ displayName: Generate the surrogate files
+ - pwsh: |
+ $nupkgs = (Get-ChildItem "$(Build.ArtifactStagingDirectory)\binaries-to-scan\*\*.*nupkg")
+ foreach ($nupkg in $nupkgs) {
+ $filename = $nupkg.Name.TrimEnd('.nupkg')
+ $dest = "$(Build.ArtifactStagingDirectory)\binaries-to-scan\nuget_symbols-extracted\$filename"
+ Write-Host "Extracting '$nupkg' to '$dest'..."
+ Expand-Archive $nupkg $dest
+ Remove-Item $nupkg
+ }
+ displayName: Extract all the .nupkg files
- ${{ if eq(parameters.buildPipelineType, 'tests') }}:
- stage: finalize
displayName: Finalize Build
dependsOn:
- api_diff
+ - managed
- samples
- tests
jobs:
- job: finalize # Finalize Build
displayName: Finalize Build
- pool: ${{ parameters.VM_IMAGE_HOST.pool }}
+ pool: ${{ parameters.buildAgentHost.pool }}
steps:
- checkout: none
- - template: azure-templates-variables.yml
- - template: azure-templates-github-status.yml
+ - template: /scripts/azure-templates-variables.yml@self
+ - template: /scripts/azure-templates-github-status.yml@self
parameters:
context: 'SkiaSharp-Tests'
displayName: Update the final status for the tests pipeline
diff --git a/scripts/azure-templates-wasm-matrix.yml b/scripts/azure-templates-wasm-matrix.yml
index 52730c71e4..9a383a54b5 100644
--- a/scripts/azure-templates-wasm-matrix.yml
+++ b/scripts/azure-templates-wasm-matrix.yml
@@ -1,27 +1,23 @@
parameters:
- artifactName: '' # the name of the artifact to merge this run into
buildExternals: '' # the build number to download externals from
- buildPipelineType: false
- vmImage: '' # the VM image
+ buildPipelineType: 'both' # the type of build pipeline setup
+ buildAgent: '' # the configuration for the build agent
+ use1ESPipelineTemplates: false # whether or not we are building using the internal 1ES Pipeline Templates
+ sdl: [] # the SDL properties to use for this job
emscripten: [ ]
jobs:
- ${{ each version in parameters.emscripten }}:
- - template: azure-templates-bootstrapper.yml
+ - template: /scripts/azure-templates-bootstrapper.yml@self
parameters:
name: native_wasm_${{ replace(version.displayName, '.', '_') }}_linux
displayName: WASM (${{ version.displayName }})
+ sdl: ${{ parameters.sdl }}
buildExternals: ${{ parameters.buildExternals }}
buildPipelineType: ${{ parameters.buildPipelineType }}
- vmImage: ${{ parameters.vmImage }}
+ buildAgent: ${{ parameters.buildAgent }}
+ use1ESPipelineTemplates: ${{ parameters.use1ESPipelineTemplates }}
docker: scripts/Docker/wasm
target: externals-wasm
dockerArgs: --build-arg EMSCRIPTEN_VERSION=${{ version.version }}
- additionalArgs: --emscriptenVersion=${{ version.version }} --emscriptenFeatures="${{ version.features }}"
- artifactName: ${{ parameters.artifactName }}
- postBuildSteps:
- - task: PublishBuildArtifacts@1
- displayName: Publish the native_wasm_linux artifacts
- inputs:
- artifactName: native_wasm_linux
- pathToPublish: 'output'
\ No newline at end of file
+ additionalArgs: --emscriptenVersion=${{ version.version }} --emscriptenFeatures="${{ version.features }}"
\ No newline at end of file
diff --git a/scripts/cake/externals.cake b/scripts/cake/externals.cake
index d5b4df53ed..0ee5c74526 100644
--- a/scripts/cake/externals.cake
+++ b/scripts/cake/externals.cake
@@ -40,6 +40,33 @@ Task("externals-download")
await DownloadPackageAsync("_nativeassets", "./output/native");
});
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// EXTERNALS INTEROP - re-generate the interop files
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Task("externals-interop")
+ .IsDependentOn("git-sync-deps")
+ .Does(() =>
+{
+ RunProcess("pwsh", "./utils/generate.ps1");
+
+ RunProcess("git", "diff --name-only binding/*/*.generated.cs", out var files);
+
+ if (files.Any()) {
+ Information("Generated files have changed:");
+ foreach (var file in files) {
+ Information($" - {file}");
+ }
+
+ if (Argument("validateInterop", false)) {
+ throw new Exception("Generated interop files are out of date. Please run `pwsh ./utils/generate.ps1`.");
+ } else {
+ Warning("Generated interop files are out of date. Please run `pwsh ./utils/generate.ps1`.");
+ Warning("##vso[task.logissue type=warning]Generated interop files are out of date. Please run `pwsh ./utils/generate.ps1`.");
+ }
+ }
+});
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// CLEAN - remove all the build artefacts
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/scripts/cake/native-shared.cake b/scripts/cake/native-shared.cake
index 17ea4f05e6..8c3703e3e5 100644
--- a/scripts/cake/native-shared.cake
+++ b/scripts/cake/native-shared.cake
@@ -38,23 +38,43 @@ Task("git-sync-deps")
if (actualIncrement != expectedIncrement)
throw new Exception($"The libSkiaSharp C API version did not match the expected '{expectedIncrement}', instead was '{actualIncrement}'.");
- RunProcess(PYTHON_EXE, new ProcessSettings {
- Arguments = SKIA_PATH.CombineWithFilePath("tools/git-sync-deps").FullPath,
- WorkingDirectory = SKIA_PATH.FullPath,
- });
+ RunPython(SKIA_PATH, SKIA_PATH.CombineWithFilePath("tools/git-sync-deps"));
});
////////////////////////////////////////////////////////////////////////////////////////////////////
// HELPERS
////////////////////////////////////////////////////////////////////////////////////////////////////
-void GnNinja(DirectoryPath outDir, string target, string skiaArgs)
+void RunPython(DirectoryPath working, FilePath script, string args = "")
+{
+ RunProcess(PYTHON_EXE, new ProcessSettings {
+ Arguments = $"{script.FullPath} {args}",
+ WorkingDirectory = working.FullPath,
+ });
+}
+
+void RunGn(DirectoryPath working, DirectoryPath outDir, string args = "")
{
var isCore = Context.Environment.Runtime.IsCoreClr;
var quote = IsRunningOnWindows() || isCore ? "\"" : "'";
var innerQuote = IsRunningOnWindows() || isCore ? "\\\"" : "\"";
+ RunProcess(GN_EXE, new ProcessSettings {
+ Arguments = $"gen {outDir} --script-executable={quote}{PYTHON_EXE}{quote} --args={quote}{args.Replace("'", innerQuote)}{quote}",
+ WorkingDirectory = working.FullPath,
+ });
+}
+
+void RunNinja(DirectoryPath working, DirectoryPath outDir, string target = "")
+{
+ var script = DEPOT_PATH.CombineWithFilePath("ninja.py");
+
+ RunPython(working, script, $"-C {outDir} {target}");
+}
+
+void GnNinja(DirectoryPath outDir, string target, string skiaArgs)
+{
// override win_vc with the command line args
if (!string.IsNullOrEmpty(VS_INSTALL)) {
DirectoryPath win_vc = VS_INSTALL;
@@ -67,16 +87,10 @@ void GnNinja(DirectoryPath outDir, string target, string skiaArgs)
$" is_official_build={CONFIGURATION.ToLower() == "release"} ".ToLower();
// generate native skia build files
- RunProcess(GN_EXE, new ProcessSettings {
- Arguments = $"gen out/{outDir} --script-executable={quote}{PYTHON_EXE}{quote} --args={quote}{skiaArgs.Replace("'", innerQuote)}{quote}",
- WorkingDirectory = SKIA_PATH.FullPath,
- });
+ RunGn(SKIA_PATH, $"out/{outDir}", skiaArgs);
// build native skia
- RunProcess(PYTHON_EXE, new ProcessSettings {
- Arguments = DEPOT_PATH.CombineWithFilePath("ninja.py").FullPath + $" -C out/{outDir} {target}",
- WorkingDirectory = SKIA_PATH.FullPath,
- });
+ RunNinja(SKIA_PATH, $"out/{outDir}", target);
}
bool Skip(string arch)
diff --git a/scripts/get-build-type.ps1 b/scripts/get-build-type.ps1
index 0274f9008b..ba6ccdbb36 100644
--- a/scripts/get-build-type.ps1
+++ b/scripts/get-build-type.ps1
@@ -23,26 +23,30 @@ if ($intBuildId -gt 0) {
if (("$ExternalsBuildId" -eq 'latest') -and ("$env:BUILD_REASON" -eq 'PullRequest')) {
Write-Host "All changes:"
$all = (git diff-tree --no-commit-id --name-only -r HEAD~ HEAD)
- foreach ($d in $all) {
- Write-Host " - $d"
- }
+ if ($?) {
+ foreach ($d in $all) {
+ Write-Host " - $d"
+ }
- Write-Host "Matching changes:"
- $matching = @(
- 'externals',
- 'native',
- 'scripts',
- '.gitmodules'
- )
- $requiresFull = (git diff-tree --no-commit-id --name-only -r HEAD~ HEAD @matching)
- foreach ($d in $requiresFull) {
- Write-Host " - $d"
- }
+ Write-Host "Matching changes:"
+ $matching = @(
+ 'externals',
+ 'native',
+ 'scripts',
+ '.gitmodules'
+ )
+ $requiresFull = (git diff-tree --no-commit-id --name-only -r HEAD~ HEAD @matching)
+ if ($?) {
+ foreach ($d in $requiresFull) {
+ Write-Host " - $d"
+ }
- if (-not $requiresFull) {
- Write-Host "Download-only build."
- Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]latest"
- exit 0
+ if (-not $requiresFull) {
+ Write-Host "Download-only build."
+ Write-Host "##vso[task.setvariable variable=DOWNLOAD_EXTERNALS]latest"
+ exit 0
+ }
+ }
}
}
diff --git a/scripts/guardian/APIScanSurrogates.in.xml b/scripts/guardian/APIScanSurrogates.in.xml
new file mode 100644
index 0000000000..f08a175c43
--- /dev/null
+++ b/scripts/guardian/APIScanSurrogates.in.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+ {SOFTWARE_FOLDER}
+ SRV*https://symweb
+
+
+
+
+
+
+
+
+
+
+
+
+ {SOFTWARE_FOLDER}
+ SRV*https://symweb
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {SOFTWARE_FOLDER}
+ SRV*https://symweb
+
+
+
+
+
+
+
+
+
+
+
+
+ {SOFTWARE_FOLDER}
+ SRV*https://symweb
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/install-android-package.ps1 b/scripts/install-android-package.ps1
index d646abfb89..eda63e2606 100644
--- a/scripts/install-android-package.ps1
+++ b/scripts/install-android-package.ps1
@@ -21,7 +21,7 @@ $sdkmanager = Join-Path "$latest" "bin" "sdkmanager$ext"
Set-Content -Value "y" -Path "yes.txt"
try {
if ($IsMacOS -or $IsLinux) {
- sh -c "`"$sdkmanager`" `"$($Package.Replace(';', '\;'))`" < yes.txt"
+ sh -c "'$sdkmanager' '$Package' < yes.txt"
} else {
cmd /c "`"$sdkmanager`" `"$Package`" < yes.txt"
}
diff --git a/scripts/install-android-platform.ps1 b/scripts/install-android-platform.ps1
index 3876ae015e..0e418e1cef 100644
--- a/scripts/install-android-platform.ps1
+++ b/scripts/install-android-platform.ps1
@@ -27,7 +27,7 @@ $sdkmanager = Join-Path "$latest" "bin" "sdkmanager$ext"
Set-Content -Value "y" -Path "yes.txt"
try {
if ($IsMacOS -or $IsLinux) {
- sh -c "`"$sdkmanager`" `"platforms\;android-$API`" < yes.txt"
+ sh -c "'$sdkmanager' 'platforms;android-$API' < yes.txt"
} else {
cmd /c "`"$sdkmanager`" `"platforms;android-$API`" < yes.txt"
}
diff --git a/scripts/install-openjdk.ps1 b/scripts/install-openjdk.ps1
index 9291f86cb8..3feb68f36f 100644
--- a/scripts/install-openjdk.ps1
+++ b/scripts/install-openjdk.ps1
@@ -6,50 +6,56 @@ Param(
$ErrorActionPreference = 'Stop'
-Add-Type -AssemblyName System.IO.Compression.FileSystem
+if (Test-Path (Join-Path "$env:JAVA_HOME_17_X64" "bin")) {
+ Write-Host "Java is already installed to '$env:JAVA_HOME_17_X64'..."
+ $java_home = $env:JAVA_HOME_17_X64
+} else {
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
-$HOME_DIR = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE }
+ $HOME_DIR = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE }
-if ($IsMacOS) {
- $ext = "tar.gz"
- $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-macOS-x64.tar.gz"
-} elseif ($IsLinux) {
- $ext = "tar.gz"
- $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-linux-x64.tar.gz"
-} else {
- $ext = "zip"
- $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-windows-x64.zip"
-}
+ if ($IsMacOS) {
+ $ext = "tar.gz"
+ $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-macOS-x64.tar.gz"
+ } elseif ($IsLinux) {
+ $ext = "tar.gz"
+ $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-linux-x64.tar.gz"
+ } else {
+ $ext = "zip"
+ $url = "https://aka.ms/download-jdk/microsoft-jdk-$Version-windows-x64.zip"
+ }
-$jdk = Join-Path "$HOME_DIR" "openjdk"
-if ($InstallDestination) {
- $jdk = $InstallDestination
-}
-Write-Host "Install destination is '$jdk'..."
+ $jdk = Join-Path "$HOME_DIR" "openjdk"
+ if ($InstallDestination) {
+ $jdk = $InstallDestination
+ }
+ Write-Host "Install destination is '$jdk'..."
-$jdkTemp = Join-Path "$HOME_DIR" "openjdk-temp"
-$archive = Join-Path "$jdkTemp" "openjdk.$ext"
+ $jdkTemp = Join-Path "$HOME_DIR" "openjdk-temp"
+ $archive = Join-Path "$jdkTemp" "openjdk.$ext"
-# download
-Write-Host "Downloading OpenJDK to '$archive'..."
-New-Item -ItemType Directory -Force -Path "$jdkTemp" | Out-Null
-(New-Object System.Net.WebClient).DownloadFile("$url", "$archive")
+ # download
+ Write-Host "Downloading OpenJDK to '$archive'..."
+ New-Item -ItemType Directory -Force -Path "$jdkTemp" | Out-Null
+ (New-Object System.Net.WebClient).DownloadFile("$url", "$archive")
-# install
-Write-Host "Extracting OpenJDK to '$jdk'..."
-New-Item -ItemType Directory -Force -Path "$jdk" | Out-Null
-if ($IsMacOS -or $IsLinux) {
- tar -vxzf "$archive" -C "$jdk"
-} else {
- [System.IO.Compression.ZipFile]::ExtractToDirectory("$archive", "$jdk")
-}
+ # install
+ Write-Host "Extracting OpenJDK to '$jdk'..."
+ New-Item -ItemType Directory -Force -Path "$jdk" | Out-Null
+ if ($IsMacOS -or $IsLinux) {
+ tar -vxzf "$archive" -C "$jdk"
+ } else {
+ [System.IO.Compression.ZipFile]::ExtractToDirectory("$archive", "$jdk")
+ }
-# set the JAVA_HOME
-if ($IsMacOS) {
- $java_home = Join-Path "$jdk" "jdk-$FolderVersion/Contents/Home"
-} else {
- $java_home = Join-Path "$jdk" "jdk-$FolderVersion"
+ # set the JAVA_HOME
+ if ($IsMacOS) {
+ $java_home = Join-Path "$jdk" "jdk-$FolderVersion/Contents/Home"
+ } else {
+ $java_home = Join-Path "$jdk" "jdk-$FolderVersion"
+ }
}
+
Write-Host "##vso[task.setvariable variable=JAVA_HOME;]$java_home"
$env:JAVA_HOME = "$java_home"
diff --git a/scripts/install-python.ps1 b/scripts/install-python.ps1
index 029a0869c7..6002b96e5e 100644
--- a/scripts/install-python.ps1
+++ b/scripts/install-python.ps1
@@ -31,12 +31,9 @@ if ($IsMacOS) {
} else {
$platform = "win32"
}
-
-$downloadUrl = (($pythonManifest
- | Where-Object { $_.version -eq $Version }
- | Select-Object -First 1).files
- | Where-Object { $_.platform -eq $platform -and $_.arch -eq $Arch }
- | Select-Object -First 1).download_url
+$manifestFileVersion = $pythonManifest | Where-Object { $_.version -eq $Version } | Select-Object -First 1
+$manifestFileItem = $manifestFileVersion.files | Where-Object { $_.platform -eq $platform -and $_.arch -eq $Arch } | Select-Object -First 1
+$downloadUrl = $manifestFileItem.download_url
# download
$tempDir = Join-Path "$HOME_DIR" "python-temp"
diff --git a/scripts/vcvarsall.bat b/scripts/vcvarsall.bat
new file mode 100644
index 0000000000..52a6e62855
--- /dev/null
+++ b/scripts/vcvarsall.bat
@@ -0,0 +1,33 @@
+@echo off
+
+REM Check if all three arguments are provided
+if "%~2"=="" (
+ echo Usage: %0 ^ ^ ^