@sapui5/sap.ui.vk 1.120.12 → 1.120.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/package.json +1 -1
  2. package/src/sap/ui/vk/.library +1 -1
  3. package/src/sap/ui/vk/AnimationPlayback.js +1 -1
  4. package/src/sap/ui/vk/AnimationPlayer.js +1 -1
  5. package/src/sap/ui/vk/AnimationSequence.js +1 -1
  6. package/src/sap/ui/vk/AnimationTimeSlider.js +1 -1
  7. package/src/sap/ui/vk/AnimationTrack.js +1 -1
  8. package/src/sap/ui/vk/Annotation.js +1 -1
  9. package/src/sap/ui/vk/BaseNodeProxy.js +1 -1
  10. package/src/sap/ui/vk/Camera.js +1 -1
  11. package/src/sap/ui/vk/ContentConnector.js +1 -1
  12. package/src/sap/ui/vk/ContentManager.js +1 -1
  13. package/src/sap/ui/vk/ContentResource.js +1 -1
  14. package/src/sap/ui/vk/Core.js +1 -1
  15. package/src/sap/ui/vk/DownloadManager.js +1 -1
  16. package/src/sap/ui/vk/DrawerToolbar.js +1 -1
  17. package/src/sap/ui/vk/DvlException.js +1 -1
  18. package/src/sap/ui/vk/FlexibleControl.js +1 -1
  19. package/src/sap/ui/vk/FlexibleControlLayoutData.js +1 -1
  20. package/src/sap/ui/vk/Highlight.js +1 -1
  21. package/src/sap/ui/vk/ImageContentManager.js +1 -1
  22. package/src/sap/ui/vk/JointUtils.js +1 -1
  23. package/src/sap/ui/vk/LayerProxy.js +1 -1
  24. package/src/sap/ui/vk/Loco.js +1 -1
  25. package/src/sap/ui/vk/Material.js +1 -1
  26. package/src/sap/ui/vk/NativeViewport.js +1 -1
  27. package/src/sap/ui/vk/NodeHierarchy.js +1 -1
  28. package/src/sap/ui/vk/NodeProxy.js +1 -1
  29. package/src/sap/ui/vk/NodeUtils.js +1 -1
  30. package/src/sap/ui/vk/Notifications.js +1 -1
  31. package/src/sap/ui/vk/OrthographicCamera.js +1 -1
  32. package/src/sap/ui/vk/PerspectiveCamera.js +1 -1
  33. package/src/sap/ui/vk/ProgressIndicator.js +1 -1
  34. package/src/sap/ui/vk/RedlineCollaboration.js +1 -1
  35. package/src/sap/ui/vk/RedlineConversation.js +1 -1
  36. package/src/sap/ui/vk/RedlineDesign.js +1 -1
  37. package/src/sap/ui/vk/RedlineElement.js +1 -1
  38. package/src/sap/ui/vk/RedlineElementComment.js +1 -1
  39. package/src/sap/ui/vk/RedlineElementEllipse.js +1 -1
  40. package/src/sap/ui/vk/RedlineElementFreehand.js +1 -1
  41. package/src/sap/ui/vk/RedlineElementLine.js +1 -1
  42. package/src/sap/ui/vk/RedlineElementRectangle.js +1 -1
  43. package/src/sap/ui/vk/RedlineElementText.js +1 -1
  44. package/src/sap/ui/vk/RedlineSurface.js +1 -1
  45. package/src/sap/ui/vk/SafeArea.js +1 -1
  46. package/src/sap/ui/vk/Scene.js +1 -1
  47. package/src/sap/ui/vk/SceneTree.js +1 -1
  48. package/src/sap/ui/vk/StepNavigation.js +1 -1
  49. package/src/sap/ui/vk/Texture.js +1 -1
  50. package/src/sap/ui/vk/ToggleMenuButton.js +1 -1
  51. package/src/sap/ui/vk/ToggleMenuItem.js +1 -1
  52. package/src/sap/ui/vk/Toolbar.js +1 -1
  53. package/src/sap/ui/vk/View.js +1 -1
  54. package/src/sap/ui/vk/ViewGallery.js +1 -1
  55. package/src/sap/ui/vk/ViewGalleryThumbnail.js +1 -1
  56. package/src/sap/ui/vk/ViewGroup.js +1 -1
  57. package/src/sap/ui/vk/ViewManager.js +1 -1
  58. package/src/sap/ui/vk/ViewStateManager.js +1 -1
  59. package/src/sap/ui/vk/ViewStateManagerBase.js +1 -1
  60. package/src/sap/ui/vk/Viewer.js +1 -1
  61. package/src/sap/ui/vk/Viewport.js +28 -1
  62. package/src/sap/ui/vk/ViewportBase.js +16 -1
  63. package/src/sap/ui/vk/dvl/BaseNodeProxy.js +1 -1
  64. package/src/sap/ui/vk/dvl/ContentManager.js +1 -1
  65. package/src/sap/ui/vk/dvl/GraphicsCore.js +1 -1
  66. package/src/sap/ui/vk/dvl/LayerProxy.js +1 -1
  67. package/src/sap/ui/vk/dvl/NodeHierarchy.js +1 -1
  68. package/src/sap/ui/vk/dvl/NodeProxy.js +1 -1
  69. package/src/sap/ui/vk/dvl/Scene.js +1 -1
  70. package/src/sap/ui/vk/dvl/ViewStateManager.js +1 -1
  71. package/src/sap/ui/vk/dvl/Viewport.js +1 -1
  72. package/src/sap/ui/vk/i18n/messagebundle_es.properties +1 -1
  73. package/src/sap/ui/vk/i18n/messagebundle_iw.properties +1 -1
  74. package/src/sap/ui/vk/library.js +2 -2
  75. package/src/sap/ui/vk/matai/MataiLoaderWorker.js +29 -7
  76. package/src/sap/ui/vk/measurements/Angle.js +1 -1
  77. package/src/sap/ui/vk/measurements/Area.js +1 -1
  78. package/src/sap/ui/vk/measurements/Distance.js +1 -1
  79. package/src/sap/ui/vk/measurements/Edge.js +1 -1
  80. package/src/sap/ui/vk/measurements/Face.js +1 -1
  81. package/src/sap/ui/vk/measurements/Feature.js +1 -1
  82. package/src/sap/ui/vk/measurements/Vertex.js +1 -1
  83. package/src/sap/ui/vk/svg/BaseNodeProxy.js +1 -1
  84. package/src/sap/ui/vk/svg/ContentDeliveryService.js +1 -1
  85. package/src/sap/ui/vk/svg/ContentManager.js +1 -1
  86. package/src/sap/ui/vk/svg/Element.js +133 -24
  87. package/src/sap/ui/vk/svg/Ellipse.js +4 -0
  88. package/src/sap/ui/vk/svg/NodeHierarchy.js +49 -1
  89. package/src/sap/ui/vk/svg/NodeProxy.js +1 -1
  90. package/src/sap/ui/vk/svg/OrthographicCamera.js +1 -1
  91. package/src/sap/ui/vk/svg/Scene.js +1 -1
  92. package/src/sap/ui/vk/svg/SceneBuilder.js +48 -5
  93. package/src/sap/ui/vk/svg/Text.js +82 -30
  94. package/src/sap/ui/vk/svg/ViewStateManager.js +1 -1
  95. package/src/sap/ui/vk/svg/Viewport.js +138 -20
  96. package/src/sap/ui/vk/svg/ViewportRenderer.js +90 -5
  97. package/src/sap/ui/vk/threejs/AnimationHelper.js +1 -1
  98. package/src/sap/ui/vk/threejs/BaseNodeProxy.js +1 -1
  99. package/src/sap/ui/vk/threejs/Billboard.js +2 -2
  100. package/src/sap/ui/vk/threejs/Callout.js +1 -1
  101. package/src/sap/ui/vk/threejs/ContentDeliveryService.js +1 -1
  102. package/src/sap/ui/vk/threejs/ContentManager.js +1 -1
  103. package/src/sap/ui/vk/threejs/DetailView.js +1 -1
  104. package/src/sap/ui/vk/threejs/HighlightPlayer.js +2 -2
  105. package/src/sap/ui/vk/threejs/Material.js +1 -1
  106. package/src/sap/ui/vk/threejs/NodeHierarchy.js +1 -1
  107. package/src/sap/ui/vk/threejs/NodeProxy.js +1 -1
  108. package/src/sap/ui/vk/threejs/NodesTransitionHelper.js +1 -1
  109. package/src/sap/ui/vk/threejs/OrthographicCamera.js +1 -1
  110. package/src/sap/ui/vk/threejs/PerspectiveCamera.js +1 -1
  111. package/src/sap/ui/vk/threejs/PointCloudGroup.js +1 -1
  112. package/src/sap/ui/vk/threejs/Scene.js +1 -1
  113. package/src/sap/ui/vk/threejs/SceneBuilder.js +2 -2
  114. package/src/sap/ui/vk/threejs/Texture.js +1 -1
  115. package/src/sap/ui/vk/threejs/Thrustline.js +1 -1
  116. package/src/sap/ui/vk/threejs/ViewStateManager.js +1 -1
  117. package/src/sap/ui/vk/threejs/Viewport.js +1 -1
  118. package/src/sap/ui/vk/threejs/v2/ViewStateManager.js +1 -1
  119. package/src/sap/ui/vk/tools/AnchorPointTool.js +1 -1
  120. package/src/sap/ui/vk/tools/AnchorPointToolGizmo.js +1 -1
  121. package/src/sap/ui/vk/tools/AxisAngleRotationTool.js +1 -1
  122. package/src/sap/ui/vk/tools/AxisAngleRotationToolGizmo.js +1 -1
  123. package/src/sap/ui/vk/tools/CreateEllipseTool.js +1 -1
  124. package/src/sap/ui/vk/tools/CreateEllipseToolGizmo.js +1 -1
  125. package/src/sap/ui/vk/tools/CreateParametricGizmo.js +1 -1
  126. package/src/sap/ui/vk/tools/CreatePathTool.js +1 -1
  127. package/src/sap/ui/vk/tools/CreatePathToolGizmo.js +1 -1
  128. package/src/sap/ui/vk/tools/CreateRectangleTool.js +1 -1
  129. package/src/sap/ui/vk/tools/CreateRectangleToolGizmo.js +1 -1
  130. package/src/sap/ui/vk/tools/CreateTextTool.js +1 -1
  131. package/src/sap/ui/vk/tools/CreateTextToolGizmo.js +1 -1
  132. package/src/sap/ui/vk/tools/CrossSectionTool.js +1 -1
  133. package/src/sap/ui/vk/tools/CrossSectionToolGizmo.js +1 -1
  134. package/src/sap/ui/vk/tools/DuplicateSvgElementTool.js +1 -1
  135. package/src/sap/ui/vk/tools/DuplicateSvgElementToolGizmo.js +1 -1
  136. package/src/sap/ui/vk/tools/ExplodeTool.js +1 -1
  137. package/src/sap/ui/vk/tools/ExplodeToolGizmo.js +1 -1
  138. package/src/sap/ui/vk/tools/Gizmo.js +1 -1
  139. package/src/sap/ui/vk/tools/HitTestTool.js +1 -1
  140. package/src/sap/ui/vk/tools/MoveTool.js +1 -1
  141. package/src/sap/ui/vk/tools/MoveToolGizmo.js +1 -1
  142. package/src/sap/ui/vk/tools/PointCloudSelectionTool.js +1 -1
  143. package/src/sap/ui/vk/tools/PointCloudSelectionToolGizmo.js +1 -1
  144. package/src/sap/ui/vk/tools/RectSelectTool.js +1 -1
  145. package/src/sap/ui/vk/tools/RedlineTool.js +1 -1
  146. package/src/sap/ui/vk/tools/RedlineToolGizmo.js +1 -1
  147. package/src/sap/ui/vk/tools/RotateOrbitTool.js +1 -1
  148. package/src/sap/ui/vk/tools/RotateTool.js +1 -1
  149. package/src/sap/ui/vk/tools/RotateToolGizmo.js +1 -1
  150. package/src/sap/ui/vk/tools/RotateTurntableTool.js +1 -1
  151. package/src/sap/ui/vk/tools/ScaleTool.js +1 -1
  152. package/src/sap/ui/vk/tools/ScaleToolGizmo.js +1 -1
  153. package/src/sap/ui/vk/tools/SceneOrientationTool.js +1 -1
  154. package/src/sap/ui/vk/tools/SceneOrientationToolGizmo.js +1 -1
  155. package/src/sap/ui/vk/tools/Tool.js +1 -1
  156. package/src/sap/ui/vk/tools/TooltipTool.js +1 -1
  157. package/src/sap/ui/vk/tools/TooltipToolGizmo.js +1 -1
  158. package/src/sap/ui/vk/tools/TransformSvgElementTool.js +1 -1
  159. package/src/sap/ui/vk/tools/TransformSvgElementToolGizmo.js +3 -3
  160. package/src/sap/ui/vk/tools/TransformSvgElementToolHandler.js +1 -1
  161. package/src/sap/ui/vk/ve/dvl.js +7 -7
  162. package/src/sap/ui/vk/ve/dvl.wasm +0 -0
  163. package/src/sap/ui/vk/ve/matai.js +2 -2
  164. package/src/sap/ui/vk/ve/matai.wasm +0 -0
@@ -10,6 +10,7 @@ sap.ui.define([
10
10
  "../NodeHierarchy",
11
11
  "sap/ui/base/ObjectPool",
12
12
  "./Element",
13
+ "./Text",
13
14
  "./BaseNodeProxy",
14
15
  "./NodeProxy",
15
16
  "../Messages",
@@ -22,6 +23,7 @@ sap.ui.define([
22
23
  NodeHierarchyBase,
23
24
  ObjectPool,
24
25
  Element,
26
+ Text, // needed for Element.setCustomText to work
25
27
  BaseNodeProxy,
26
28
  NodeProxy,
27
29
  Messages,
@@ -55,7 +57,7 @@ sap.ui.define([
55
57
  *
56
58
  * @public
57
59
  * @author SAP SE
58
- * @version 1.120.12
60
+ * @version 1.120.13
59
61
  * @extends sap.ui.vk.NodeHierarchy
60
62
  * @alias sap.ui.vk.svg.NodeHierarchy
61
63
  */
@@ -599,5 +601,51 @@ sap.ui.define([
599
601
  return this;
600
602
  };
601
603
 
604
+ /**
605
+ * Attaches a custom text to this elements.
606
+ * @param {sap.ui.vk.svg.Element|sap.ui.vk.svg.Element[]} nodeRefs The node or array of nodes to set the custom text to.
607
+ * @param {object} [options] The custom text options. If not specified, the existing custom text will be removed.
608
+ * @param {string} [options.text] The text to display, it's mutually exclusive with <code>htmlText</code> option.
609
+ * Line breaks are not supported, use <code>htmlText</code> option for multi-line text.
610
+ * @param {string} [options.htmlText] The HTML text to display, it's mutually exclusive with <code>text</code> option.
611
+ * Line breaks are supported using paragraphs: <code>"&lt;p&gt;Line 1&lt;/p&gt;&lt;p&gt;Line 2&lt;/p&gt;"</code>.
612
+ * @param {number} [options.size] The font size of the text in scene coordinate units. If not specified then the size will be
613
+ * automatically determined based on the median text size in the scene or computed from the bounding box of the scene, but better
614
+ * to specify it explicitly to avoid unexpected results.
615
+ * @param {string} [options.fontFamily] The font family of the text. Default is <code>"Arial"</code>.
616
+ * @param {string} [options.fontStyle] The font style of the text (normal | italic | oblique). Default is undefined ("normal").
617
+ * @param {string} [options.fontWeight] The font weight of the text (normal | bold | bolder | lighter | <number>). Default is undefined ("normal").
618
+ * @param {string} [options.textDecoration] The text decoration of the text (none | underline | line-through, etc). Default is undefined ("none").
619
+ * @param {string} [options.fill] The fill color of the text in CSS format. Default is "black".
620
+ * @param {number[]} [options.pivot] The pivot point of the custom text, relative to the text bounding box.
621
+ * The pivot point is used together with the anchor point to position the text.
622
+ * Default is <code>[0.5, 0.5]</code> (middle of the custom text). <code>[0, 0]</code> is top-left, <code>[1, 1]</code> is bottom-right.
623
+ * @param {number[]} [options.anchor] The anchor point of the text, relative to the bounding box of the node to which
624
+ * the custom text is attached.
625
+ * Default is <code>[0.5, 0.5]</code> (center of node). <code>[0, 0]</code> is top-left, <code>[1, 1]</code> is bottom-right.
626
+ * @returns {this} <code>this</code> to allow method chaining.
627
+ * @public
628
+ * @experimental
629
+ * @since 1.120.0
630
+ * @example <caption>Add custom text to the center of the <code>nodeRef</code> with HTML formatting and three separate lines of text:</caption>
631
+ * nodeHierarchy.setCustomText(nodeRef, {
632
+ * htmlText: `&lt;p&gt;Line &lt;strong&gt;1&lt;/strong&gt;&lt;/p&gt;
633
+ * &lt;p&gt;Line &lt;em&gt;2&lt;/em&gt;&lt;/p&gt;
634
+ * &lt;p&gt;Line &lt;span style="font-size: 24pt;color: blue;font-family: 'courier new';"&gt;3&lt;/span&gt;&lt;/p&gt;`,
635
+ * size: 16,
636
+ * fontFamily: "lucida console, monospace",
637
+ * fill: "red",
638
+ * pivot: [0.5, 0.5],
639
+ * anchor: [0.5, 0.5]
640
+ * });
641
+ */
642
+ NodeHierarchy.prototype.setCustomText = function(nodeRefs, options) {
643
+ nodeRefs = Array.isArray(nodeRefs) ? nodeRefs : [nodeRefs];
644
+ nodeRefs.forEach(function(nodeRef) {
645
+ nodeRef.setCustomText(options);
646
+ });
647
+ return this;
648
+ };
649
+
602
650
  return NodeHierarchy;
603
651
  });
@@ -36,7 +36,7 @@ sap.ui.define([
36
36
  *
37
37
  * @public
38
38
  * @author SAP SE
39
- * @version 1.120.12
39
+ * @version 1.120.13
40
40
  * @extends sap.ui.vk.NodeProxy
41
41
  * @alias sap.ui.vk.svg.NodeProxy
42
42
  */
@@ -22,7 +22,7 @@ sap.ui.define([
22
22
  *
23
23
  * @public
24
24
  * @author SAP SE
25
- * @version 1.120.12
25
+ * @version 1.120.13
26
26
  * @extends sap.ui.vk.OrthographicCamera
27
27
  * @alias sap.ui.vk.svg.OrthographicCamera
28
28
  * @since 1.80.0
@@ -26,7 +26,7 @@ sap.ui.define([
26
26
  *
27
27
  * @public
28
28
  * @author SAP SE
29
- * @version 1.120.12
29
+ * @version 1.120.13
30
30
  * @extends sap.ui.vk.Scene
31
31
  * @alias sap.ui.vk.svg.Scene
32
32
  */
@@ -64,7 +64,7 @@ sap.ui.define([
64
64
  *
65
65
  * @private
66
66
  * @author SAP SE
67
- * @version 1.120.12
67
+ * @version 1.120.13
68
68
  * @experimental Since 1.81.0 This class is experimental and might be modified or removed in future versions.
69
69
  */
70
70
  var SceneBuilder = function(rootNode, contentResource, resolve, reject) {
@@ -133,14 +133,44 @@ sap.ui.define([
133
133
  this._reject(err);
134
134
  } else {
135
135
  this._yIndex = 1; // VDS4 file geometry data
136
- this._rootNode.matrix[3] = info.upAxis === 2 ? -1 : 1; // (0 = +X, 1 = -X, 2 = +Y, 3 = -Y, 4 = +Z, 5 = -Z)
137
- var camera = this._cameras.get(info.cameraId);
136
+ this._rootNode.matrix[3] = info.upAxis === 2 || info.upAxis === 4 ? -1 : 1; // (0 = +X, 1 = -X, 2 = +Y, 3 = -Y, 4 = +Z, 5 = -Z)
137
+ const camera = this._cameras.get(info.cameraId);
138
+ const outputSettings = info.outputSettings;
139
+ if (outputSettings && camera) {
140
+ // update line width in materials if coordinate space is in device/paper units
141
+ const outputDPI = 72; // ignore outputSettings.dpi as VEA ignores DPI setting and always uses 72 DPI
142
+ const mmPerInch = 25.4; // 1 inch = 25.4 mm
143
+ const outputSizeMM = Math.min(outputSettings.width, outputSettings.height); // in mm
144
+ const outputSize = outputSizeMM * (outputDPI / mmPerInch); // in dots (1 dot = 1/72 inch)
145
+ const mediumViewportSize = 768; // medium viewport size in pixels (1024x768)
146
+ // console.log(`setScene outputSettings: ${JSON.stringify(outputSettings)}`);
147
+
148
+ this._materialMap.forEach(function(material) {
149
+ if (material.lineStyle.widthCoordinateSpace === 3) { // sap::ve::core::Material::CoordinateSpace::NormalizedViewport
150
+ // 2D viewport space (x and y values range from -1.0 to 1.0, the origin representing the center of view)
151
+ material.lineWidth = material.lineStyle.width * mediumViewportSize * 0.5; // 768 is a medium viewport size in pixels
152
+ material.lineStyle.widthCoordinateSpace = 0; // convert to screen space
153
+ } else if (material.lineStyle.widthCoordinateSpace === 4) { // sap::ve::core::Material::CoordinateSpace::Device (device/paper units)
154
+ if (info.showPaperSpace) {
155
+ // this mode requires conversion to world space units, so that the line thickness is affected by initial camera zoom factor
156
+ material.lineWidth = material.lineStyle.width * 2 / (outputSize * camera._initialZoom);
157
+ } else {
158
+ // this mode has a weird behavior in VE Author, the line thickness is measured in weird units that are converted
159
+ // to pixels (doesn't depend on the zoom factor), but it depends on the viewport size
160
+ material.lineWidth = material.lineStyle.width * mediumViewportSize / outputSize;
161
+ material.lineStyle.widthCoordinateSpace = 0; // convert to screen space
162
+ }
163
+ }
164
+ });
165
+ }
166
+
138
167
  Log.info("setScene", JSON.stringify(info), camera);
139
- this._resolve({
168
+ this._resolve?.({
140
169
  node: this._rootNode,
141
- camera: camera,
170
+ camera,
142
171
  backgroundTopColor: info.backgroundTopColor,
143
172
  backgroundBottomColor: info.backgroundBottomColor,
173
+ outputSettings,
144
174
  contentResource: this._contentResource,
145
175
  builder: this
146
176
  });
@@ -359,6 +389,19 @@ sap.ui.define([
359
389
  }
360
390
  };
361
391
 
392
+ SceneBuilder.prototype.setSubmeshes = function(meshes) {
393
+ var mesh, submeshes, submesh, j, len;
394
+ for (var i = 0, count = meshes.length; i < count; ++i) {
395
+ mesh = meshes[i];
396
+ submeshes = mesh.submeshes;
397
+
398
+ for (j = 0, len = submeshes.length; j < len; ++j) {
399
+ submesh = submeshes[j];
400
+ this.insertSubmesh(submesh);
401
+ }
402
+ }
403
+ };
404
+
362
405
  SceneBuilder.prototype.insertSubmesh = function(submeshInfo) {
363
406
  // console.log("insertSubmesh", submeshInfo);
364
407
  if (!submeshInfo.lods) {
@@ -17,6 +17,11 @@ sap.ui.define([
17
17
  ) {
18
18
  "use strict";
19
19
 
20
+ // Parametric text content types (sap::ve::core::ParametricType)
21
+ const ptParametricTextData = 10;
22
+ const ptParametricTextSpan = 11;
23
+ const ptParametricTextPath = 12;
24
+
20
25
  var Text = function(parameters) {
21
26
  parameters = parameters || {};
22
27
  Element.call(this, parameters);
@@ -28,12 +33,11 @@ sap.ui.define([
28
33
  this.style.size = this.style.size || "1em";
29
34
  this.x = parameters.x || 0;
30
35
  this.y = parameters.y || 0;
31
- if (parameters.dx) {
32
- this.dx = parameters.dx;
33
- }
34
- if (parameters.dy) {
35
- this.dy = parameters.dy;
36
- }
36
+ ["dx", "dy", "textAnchor", "alignmentBaseline", "pivot", "anchor"].forEach((prop) => {
37
+ if (parameters[prop] != null) {
38
+ this[prop] = parameters[prop];
39
+ }
40
+ });
37
41
 
38
42
  // If not specified then set default colours for text objects
39
43
  this.fillStyle = parameters.fillStyle || { colour: [0, 0, 0, 1] };
@@ -139,6 +143,12 @@ sap.ui.define([
139
143
  if (this.dy) {
140
144
  setAttributeFunc("dy", this.dy);
141
145
  }
146
+ if (this.textAnchor) {
147
+ setAttributeFunc("text-anchor", this.textAnchor);
148
+ }
149
+ if (this.alignmentBaseline) {
150
+ setAttributeFunc("alignment-baseline", this.alignmentBaseline);
151
+ }
142
152
  setStyle(this.style, setAttributeFunc, true);
143
153
  };
144
154
 
@@ -165,12 +175,12 @@ sap.ui.define([
165
175
  for (var i = 0, l = content.length; i < l; i++) {
166
176
  var c = content[i];
167
177
  switch (c.type) {
168
- case 10: // ptParametricTextData
178
+ case ptParametricTextData:
169
179
  case undefined:
170
180
  case "text":
171
181
  rm.text(c.text);
172
182
  break;
173
- case 11: // ptParametricTextSpan
183
+ case ptParametricTextSpan:
174
184
  case "span":
175
185
  rm.openStart("tspan");
176
186
  setContentAttributes(c, setAttributeFunc);
@@ -184,7 +194,7 @@ sap.ui.define([
184
194
  renderContent(c.content, rm);
185
195
  rm.close("tspan");
186
196
  break;
187
- case 12: // ptParametricTextPath
197
+ case ptParametricTextPath:
188
198
  case "path":
189
199
  rm.openStart("textPath");
190
200
  setContentAttributes(c, setAttributeFunc);
@@ -232,12 +242,12 @@ sap.ui.define([
232
242
  for (var i = 0, l = content.length; i < l; i++) {
233
243
  var c = content[i];
234
244
  switch (c.type) {
235
- case 10: // ptParametricTextData
245
+ case ptParametricTextData:
236
246
  case undefined:
237
247
  case "text":
238
248
  parentDomRef.append(c.text);
239
249
  break;
240
- case 11: // ptParametricTextSpan
250
+ case ptParametricTextSpan:
241
251
  case "span":
242
252
  domRef = document.createElementNS(Element._svgNamespace, "tspan");
243
253
  setAttributeFunc = domRef.setAttribute.bind(domRef);
@@ -251,7 +261,7 @@ sap.ui.define([
251
261
  createContent(c.content, domRef);
252
262
  parentDomRef.append(domRef);
253
263
  break;
254
- case 12: // ptParametricTextPath
264
+ case ptParametricTextPath:
255
265
  case "path":
256
266
  domRef = document.createElementNS(Element._svgNamespace, "textPath");
257
267
  setAttributeFunc = domRef.setAttribute.bind(domRef);
@@ -289,17 +299,21 @@ sap.ui.define([
289
299
  };
290
300
 
291
301
  function toPixels(size) {
302
+ let value;
292
303
  switch (typeof size) {
293
- case "number": return size;
304
+ case "number": value = size; break;
294
305
  case "string":
295
306
  if (size.endsWith("pt")) {
296
- return parseFloat(size) * 4 / 3;
307
+ value = parseFloat(size) * 4 / 3;
297
308
  } else if (size.endsWith("em")) {
298
- return parseFloat(size) * 16;
309
+ value = parseFloat(size) * 16;
310
+ } else {
311
+ value = parseFloat(size);
299
312
  }
300
- return parseFloat(size);
301
- default: return 0;
313
+ break;
314
+ default: value = 0; break;
302
315
  }
316
+ return typeof value === "number" && isFinite(value) ? value : 0;
303
317
  }
304
318
 
305
319
  function getContent(p) {
@@ -308,12 +322,12 @@ sap.ui.define([
308
322
  var node = p.childNodes[i];
309
323
  if (node.data !== undefined) {
310
324
  content.push({
311
- type: 10,
325
+ type: ptParametricTextData,
312
326
  text: node.data
313
327
  });
314
328
  } else if (node.childNodes.length > 0) {
315
329
  var tspan = {
316
- type: 11,
330
+ type: ptParametricTextSpan,
317
331
  content: getContent(node)
318
332
  };
319
333
  var nodeStyle = node.style;
@@ -363,6 +377,7 @@ sap.ui.define([
363
377
  }
364
378
 
365
379
  Text.prototype.setHtmlTextContent = function(htmlText) {
380
+ // console.log("setHtmlTextContent", htmlText);
366
381
  var htmlElem = document.createElement("html");
367
382
  htmlElem.innerHTML = htmlText;
368
383
  var content = [];
@@ -379,8 +394,8 @@ sap.ui.define([
379
394
  y += i > 0 ? maxFontSize : 0;
380
395
  }
381
396
  content.push({
382
- type: 11,
383
- x: (node.style.paddingLeft || 0) + this.x,
397
+ type: ptParametricTextSpan,
398
+ x: toPixels(node.style.paddingLeft) + this.x,
384
399
  y: y,
385
400
  content: getContent(node)
386
401
  });
@@ -389,7 +404,7 @@ sap.ui.define([
389
404
  }
390
405
  } else if (node.data) {// text node
391
406
  content.push({
392
- type: 10,
407
+ type: ptParametricTextData,
393
408
  text: node.data
394
409
  });
395
410
  }
@@ -406,14 +421,14 @@ sap.ui.define([
406
421
  for (var i = 0; i < content.length; i++) {
407
422
  var c = content[i];
408
423
  switch (c.type) {
409
- case 10:
424
+ case ptParametricTextData:
410
425
  case undefined:
411
426
  case "text":
412
427
  value += c.text;
413
428
  break;
414
- case 11:
429
+ case ptParametricTextSpan:
415
430
  case "span":
416
- case 12:
431
+ case ptParametricTextPath:
417
432
  case "path":
418
433
  var style = c.style;
419
434
  if (!inlineContent || c.y !== undefined || c.dy !== undefined) {
@@ -485,12 +500,12 @@ sap.ui.define([
485
500
  switch (c.type) {
486
501
  case undefined:
487
502
  case "text":
488
- content.push({ type: 10, text: c.text });
503
+ content.push({ type: ptParametricTextData, text: c.text });
489
504
  break;
490
505
  default:
491
506
  case "span":
492
507
  case "path":
493
- var tspan = { type: c.type === "path" ? 12 : 11 };
508
+ var tspan = { type: c.type === "path" ? ptParametricTextPath : ptParametricTextSpan };
494
509
  if (c.x !== undefined) {
495
510
  tspan.x = c.x;
496
511
  }
@@ -524,13 +539,13 @@ sap.ui.define([
524
539
  for (var i = 0; i < content.length; i++) {
525
540
  var c = content[i];
526
541
  switch (c.type) {
527
- case 10:
542
+ case ptParametricTextData:
528
543
  case undefined:
529
544
  children.push({ text: c.text });
530
545
  break;
531
- case 11:
546
+ case ptParametricTextSpan:
532
547
  case "span":
533
- case 12:
548
+ case ptParametricTextPath:
534
549
  case "path":
535
550
  var span = { type: "span" };
536
551
  if (c.x !== undefined) {
@@ -620,5 +635,42 @@ sap.ui.define([
620
635
  return this;
621
636
  };
622
637
 
638
+ Element.prototype.setCustomText = function(options) {
639
+ if (options == null || (options.text == null && options.htmlText == null)) {
640
+ this.customText = null;
641
+ return this;
642
+ }
643
+
644
+ const customText = this.customText = new Text({
645
+ text: options.text,
646
+ pivot: options.pivot ?? [0.5, 0.5],
647
+ anchor: options.anchor ?? [0.5, 0.5],
648
+ style: {
649
+ size: options.size ?? "0px",
650
+ fontFace: options.fontFamily ?? options.fontFace ?? "Arial",
651
+ fontStyle: options.fontStyle,
652
+ fontWeight: options.fontWeight,
653
+ textDecoration: options.textDecoration,
654
+ fill: options.fill ?? "black"
655
+ }
656
+ });
657
+ if (options.htmlText) {
658
+ customText.setHtmlTextContent(options.htmlText);
659
+ }
660
+ customText.userData.customText = true; // mark the custom text element for special hit test handling
661
+ customText.parent = this;
662
+
663
+ if (this.domRef) {
664
+ this.invalidate(); // in case if the element was previously a simple group element (did not have its own domRef)
665
+ customText.domRef = customText._createDomElement();
666
+ this.domRef.appendChild(customText.domRef);
667
+ this._updateCustomText();
668
+ this._updateColor();
669
+ }
670
+
671
+ return this;
672
+ };
673
+
674
+
623
675
  return Text;
624
676
  });
@@ -47,7 +47,7 @@ sap.ui.define([
47
47
  * @param {object} [mSettings] Initial settings for the new ViewStateManager object.
48
48
  * @public
49
49
  * @author SAP SE
50
- * @version 1.120.12
50
+ * @version 1.120.13
51
51
  * @extends sap.ui.vk.ViewStateManagerBase
52
52
  * @alias sap.ui.vk.svg.ViewStateManager
53
53
  * @since 1.80.0
@@ -68,7 +68,7 @@ sap.ui.define([
68
68
  *
69
69
  * @public
70
70
  * @author SAP SE
71
- * @version 1.120.12
71
+ * @version 1.120.13
72
72
  * @extends sap.ui.vk.ViewportBase
73
73
  * @alias sap.ui.vk.svg.Viewport
74
74
  */
@@ -261,6 +261,99 @@ sap.ui.define([
261
261
  }
262
262
  };
263
263
 
264
+ Viewport.prototype._updateCustomText = function() {
265
+ const root = this._scene.getRootElement();
266
+
267
+ // collect all font sizes in the scene
268
+ const fontSizes = [];
269
+ root.traverse(function(node) {
270
+ if (node.type === "Text") {
271
+ const fontSizeCSS = node.style.size;
272
+ const fontSize = parseFloat(fontSizeCSS);
273
+ if (fontSize > 0) {
274
+ let unitScale = 1;
275
+ if (typeof fontSizeCSS === "string") {
276
+ if (fontSizeCSS.endsWith("em")) {
277
+ unitScale = 16; // assuming 1em = 16px
278
+ } else if (fontSizeCSS.endsWith("pt")) {
279
+ unitScale = 1.333; // assuming 1pt = 1.333px
280
+ }
281
+ }
282
+
283
+ const m = node._matrixWorld();
284
+ fontSizes.push(fontSize * unitScale * Math.sqrt(m[2] * m[2] + m[3] * m[3]));
285
+ }
286
+ }
287
+ });
288
+
289
+ let fontSize;
290
+ if (fontSizes.length > 0) {// take median font size
291
+ fontSizes.sort();
292
+ fontSize = fontSizes[fontSizes.length >> 1];
293
+ } else {
294
+ const bbox = root.domRef.getBBox();
295
+ fontSize = Math.max(bbox.width, bbox.height) * 0.01;
296
+ }
297
+ fontSize = Math.round(fontSize * 100) / 100; // round to 2 decimal places
298
+
299
+ root.traverse(function(node) {
300
+ if (node.customText?.style.size === "0px") { // "0px" is a special case, it means "default font size"
301
+ node.customText.style.size = fontSize + "px";
302
+ node.customText.setHtmlTextContent(node.customText.getHtmlTextContent()); // recreate the HTML content with new font size
303
+ node._updateCustomText(); // update position of the custom text
304
+ }
305
+ });
306
+ };
307
+
308
+ Viewport.prototype._updateCustomTextFilters = function() {
309
+ const domRef = this._scene?.getRootElement()?.domRef;
310
+ if (domRef) {
311
+ const blurStdDeviation = this.getHotspotCustomTextHaloWidth();
312
+ const dilateRadius = blurStdDeviation * 0.1; // 10% of blur std deviation
313
+ const outlineWidth = this.getHotspotCustomTextOutlineWidth();
314
+ const expand = Math.max(blurStdDeviation + dilateRadius, outlineWidth * 2);
315
+ const color = cssColorToColor(this.getHotspotCustomTextOutlineColor());
316
+ for (let filter of domRef.parentNode.getElementsByTagName("filter")) {
317
+ if (filter.id.endsWith("-custom-text")) {
318
+ if (sap.ui.Device.browser.firefox) {
319
+ filter.setAttribute("x", "-25%");
320
+ filter.setAttribute("y", "-100%");
321
+ filter.setAttribute("width", "150%");
322
+ filter.setAttribute("height", "300%");
323
+ } else {
324
+ filter.setAttribute("x", -expand + "px");
325
+ filter.setAttribute("y", -expand + "px");
326
+ filter.setAttribute("width", `calc(100% + ${expand * 2}px)`);
327
+ filter.setAttribute("height", `calc(100% + ${expand * 2}px)`);
328
+ }
329
+ filter.childNodes[0].setAttribute("radius", dilateRadius); // set morphology dilate radius
330
+ filter.childNodes[2].setAttribute("stdDeviation", blurStdDeviation); // set gaussian blur std deviation
331
+ filter.childNodes[3].setAttribute("radius", outlineWidth); // set morphology dilate radius
332
+ filter.childNodes[5].setAttribute("stdDeviation", outlineWidth); // set gaussian blur std deviation
333
+ filter.childNodes[4].setAttribute("values", `0 0 0 0 ${color.red / 255}, 0 0 0 0 ${color.green / 255}, 0 0 0 0 ${color.blue / 255}, 0 0 0 ${color.alpha} 0`);
334
+ }
335
+ }
336
+ }
337
+ };
338
+
339
+ Viewport.prototype.setHotspotCustomTextOutlineColor = function(cssColor) {
340
+ this.setProperty("hotspotCustomTextOutlineColor", cssColor, true);
341
+ this._updateCustomTextFilters();
342
+ return this;
343
+ };
344
+
345
+ Viewport.prototype.setHotspotCustomTextOutlineWidth = function(width) {
346
+ this.setProperty("hotspotCustomTextOutlineWidth", width, true);
347
+ this._updateCustomTextFilters();
348
+ return this;
349
+ };
350
+
351
+ Viewport.prototype.setHotspotCustomTextHaloWidth = function(width) {
352
+ this.setProperty("hotspotCustomTextHaloWidth", width, true);
353
+ this._updateCustomTextFilters();
354
+ return this;
355
+ };
356
+
264
357
  Viewport.prototype.onAfterRendering = function() {
265
358
  this._resizeListenerId = ResizeHandler.register(this, this._handleResize.bind(this));
266
359
 
@@ -271,6 +364,8 @@ sap.ui.define([
271
364
  var root = this._scene.getRootElement();
272
365
  root._setDomRef(document.getElementById(root.uid));
273
366
  this._svgElement = root.domRef.parentNode;
367
+
368
+ this._updateCustomText();
274
369
  }
275
370
 
276
371
  this._handleResize({
@@ -459,28 +554,51 @@ sap.ui.define([
459
554
 
460
555
  var rootElement = this._scene.getRootElement();
461
556
  var viewportRect = this.getDomRef().getBoundingClientRect();
557
+ x += viewportRect.x;
558
+ y += viewportRect.y;
462
559
 
463
- var hitTest = function(x, y) {
464
- var htmlElement;
465
- if (ignoreHotspots) {
466
- var htmlElements = document.elementsFromPoint(x + viewportRect.x, y + viewportRect.y);
467
- for (var i = 0; i < htmlElements.length; i++) {
468
- htmlElement = htmlElements[i];
469
- var hit = htmlElement != null && htmlElement.id ? rootElement.getElementById(htmlElement.id) : null;
470
- if (!hit) {
471
- return null;
472
- }
473
- var elem = hit._getSceneTreeElement();
474
- if (elem && elem._vkGetNodeContentType() !== NodeContentType.Hotspot) {
475
- return hit;
476
- }
560
+ function getHit(htmlElement) {
561
+ while (htmlElement && !htmlElement.id) {
562
+ htmlElement = htmlElement.parentElement; // go up the DOM tree to find an element with id
563
+ }
564
+ if (!htmlElement) {
565
+ return null; // element not found
566
+ }
567
+
568
+ const hit = rootElement.getElementById(htmlElement.id);
569
+ const elem = hit?._getSceneTreeElement();
570
+ if (!elem) {
571
+ return null; // element not found in the scene
572
+ }
573
+
574
+ if (hit.userData.customText && hit.parent && hit.parent._vkGetNodeContentType() === NodeContentType.DynamicContent) {
575
+ return hit.parent;
576
+ }
577
+
578
+ if ((ignoreHotspots && elem._vkGetNodeContentType() === NodeContentType.Hotspot) ||
579
+ hit.userData.customText) {
580
+ return undefined; // ignore hotspots if the "ignoreHotspots" flag is set and ignore custom text elements
581
+ }
582
+
583
+ return hit;
584
+ }
585
+
586
+ function hitTest(x, y) {
587
+ const htmlElement = document.elementFromPoint(x, y);
588
+ const hit = getHit(htmlElement);
589
+ if (hit !== undefined) {
590
+ return hit;
591
+ }
592
+
593
+ for (let htmlElement of document.elementsFromPoint(x, y)) {
594
+ const hit = getHit(htmlElement);
595
+ if (hit !== undefined) {
596
+ return hit;
477
597
  }
478
- return null;
479
- } else {
480
- htmlElement = document.elementFromPoint(x + viewportRect.x, y + viewportRect.y);
481
- return htmlElement !== null && htmlElement.id ? rootElement.getElementById(htmlElement.id) : null;
482
598
  }
483
- };
599
+
600
+ return null; // no hit found
601
+ }
484
602
 
485
603
  var hit = hitTest(x, y);
486
604
  if (withTolerance) {