blockly 7.20211209.4 → 8.0.1

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 (231) hide show
  1. package/blockly.d.ts +18963 -18432
  2. package/blockly.min.js +5 -4
  3. package/blockly_compressed.js +4 -3
  4. package/blockly_compressed.js.map +1 -1
  5. package/blocks/blocks.js +47 -0
  6. package/blocks/colour.js +13 -3
  7. package/blocks/lists.js +22 -13
  8. package/blocks/logic.js +13 -3
  9. package/blocks/loops.js +24 -11
  10. package/blocks/math.js +12 -3
  11. package/blocks/procedures.js +45 -32
  12. package/blocks/text.js +22 -13
  13. package/blocks/variables.js +14 -3
  14. package/blocks/variables_dynamic.js +13 -3
  15. package/blocks_compressed.js +1 -1
  16. package/blocks_compressed.js.map +1 -1
  17. package/core/block.js +1869 -1814
  18. package/core/block_drag_surface.js +201 -200
  19. package/core/block_dragger.js +377 -373
  20. package/core/block_svg.js +1593 -1479
  21. package/core/blockly.js +8 -22
  22. package/core/blocks.js +9 -2
  23. package/core/browser_events.js +22 -5
  24. package/core/bubble.js +841 -797
  25. package/core/bubble_dragger.js +213 -206
  26. package/core/bump_objects.js +2 -2
  27. package/core/clipboard.js +9 -9
  28. package/core/comment.js +353 -332
  29. package/core/common.js +46 -17
  30. package/core/component_manager.js +181 -174
  31. package/core/config.js +87 -0
  32. package/core/connection.js +595 -584
  33. package/core/connection_checker.js +242 -244
  34. package/core/connection_db.js +235 -230
  35. package/core/contextmenu.js +9 -6
  36. package/core/contextmenu_items.js +1 -2
  37. package/core/contextmenu_registry.js +93 -89
  38. package/core/css.js +474 -474
  39. package/core/delete_area.js +45 -42
  40. package/core/drag_target.js +57 -56
  41. package/core/dropdowndiv.js +153 -163
  42. package/core/events/events.js +2 -2
  43. package/core/events/events_abstract.js +89 -77
  44. package/core/events/events_block_base.js +37 -36
  45. package/core/events/events_block_change.js +130 -124
  46. package/core/events/events_block_create.js +73 -71
  47. package/core/events/events_block_delete.js +84 -82
  48. package/core/events/events_block_drag.js +50 -49
  49. package/core/events/events_block_move.js +147 -140
  50. package/core/events/events_bubble_open.js +51 -50
  51. package/core/events/events_click.js +48 -44
  52. package/core/events/events_comment_base.js +72 -69
  53. package/core/events/events_comment_change.js +63 -61
  54. package/core/events/events_comment_create.js +44 -42
  55. package/core/events/events_comment_delete.js +42 -40
  56. package/core/events/events_comment_move.js +106 -104
  57. package/core/events/events_marker_move.js +65 -64
  58. package/core/events/events_selected.js +46 -45
  59. package/core/events/events_theme_change.js +36 -35
  60. package/core/events/events_toolbox_item_select.js +46 -45
  61. package/core/events/events_trashcan_open.js +37 -36
  62. package/core/events/events_ui.js +47 -46
  63. package/core/events/events_ui_base.js +30 -29
  64. package/core/events/events_var_base.js +37 -36
  65. package/core/events/events_var_create.js +50 -48
  66. package/core/events/events_var_delete.js +50 -48
  67. package/core/events/events_var_rename.js +51 -49
  68. package/core/events/events_viewport.js +66 -65
  69. package/core/events/utils.js +29 -14
  70. package/core/events/workspace_events.js +49 -55
  71. package/core/extensions.js +4 -3
  72. package/core/field.js +1061 -997
  73. package/core/field_angle.js +462 -442
  74. package/core/field_checkbox.js +194 -182
  75. package/core/field_colour.js +519 -505
  76. package/core/field_dropdown.js +617 -598
  77. package/core/field_image.js +229 -220
  78. package/core/field_label.js +102 -91
  79. package/core/field_label_serializable.js +42 -41
  80. package/core/field_multilineinput.js +372 -358
  81. package/core/field_number.js +272 -253
  82. package/core/field_textinput.js +499 -467
  83. package/core/field_variable.js +458 -420
  84. package/core/flyout_base.js +1005 -952
  85. package/core/flyout_button.js +277 -260
  86. package/core/flyout_horizontal.js +304 -302
  87. package/core/flyout_metrics_manager.js +64 -64
  88. package/core/flyout_vertical.js +306 -300
  89. package/core/generator.js +459 -446
  90. package/core/gesture.js +829 -813
  91. package/core/grid.js +166 -163
  92. package/core/icon.js +168 -159
  93. package/core/inject.js +7 -5
  94. package/core/input.js +257 -248
  95. package/core/insertion_marker_manager.js +655 -624
  96. package/core/internal_constants.js +0 -129
  97. package/core/keyboard_nav/ast_node.js +605 -596
  98. package/core/keyboard_nav/basic_cursor.js +166 -165
  99. package/core/keyboard_nav/cursor.js +99 -97
  100. package/core/keyboard_nav/marker.js +83 -79
  101. package/core/keyboard_nav/tab_navigate_cursor.js +18 -23
  102. package/core/marker_manager.js +153 -141
  103. package/core/menu.js +377 -372
  104. package/core/menuitem.js +223 -217
  105. package/core/metrics_manager.js +403 -390
  106. package/core/mutator.js +468 -437
  107. package/core/names.js +229 -188
  108. package/core/options.js +290 -284
  109. package/core/procedures.js +29 -17
  110. package/core/registry.js +19 -16
  111. package/core/rendered_connection.js +482 -463
  112. package/core/renderers/common/block_rendering.js +9 -3
  113. package/core/renderers/common/constants.js +1119 -1112
  114. package/core/renderers/common/debug.js +14 -0
  115. package/core/renderers/common/debugger.js +338 -316
  116. package/core/renderers/common/drawer.js +380 -370
  117. package/core/renderers/common/i_path_object.js +2 -2
  118. package/core/renderers/common/info.js +626 -618
  119. package/core/renderers/common/marker_svg.js +579 -541
  120. package/core/renderers/common/path_object.js +203 -200
  121. package/core/renderers/common/renderer.js +220 -218
  122. package/core/renderers/geras/constants.js +36 -36
  123. package/core/renderers/geras/drawer.js +155 -147
  124. package/core/renderers/geras/highlight_constants.js +244 -238
  125. package/core/renderers/geras/highlighter.js +231 -179
  126. package/core/renderers/geras/info.js +392 -369
  127. package/core/renderers/geras/measurables/inline_input.js +25 -19
  128. package/core/renderers/geras/measurables/statement_input.js +23 -17
  129. package/core/renderers/geras/path_object.js +106 -121
  130. package/core/renderers/geras/renderer.js +96 -98
  131. package/core/renderers/measurables/base.js +30 -18
  132. package/core/renderers/measurables/bottom_row.js +83 -80
  133. package/core/renderers/measurables/connection.js +22 -15
  134. package/core/renderers/measurables/external_value_input.js +35 -22
  135. package/core/renderers/measurables/field.js +35 -20
  136. package/core/renderers/measurables/hat.js +18 -13
  137. package/core/renderers/measurables/icon.js +24 -17
  138. package/core/renderers/measurables/in_row_spacer.js +15 -13
  139. package/core/renderers/measurables/inline_input.js +43 -33
  140. package/core/renderers/measurables/input_connection.js +41 -28
  141. package/core/renderers/measurables/input_row.js +50 -44
  142. package/core/renderers/measurables/jagged_edge.js +14 -12
  143. package/core/renderers/measurables/next_connection.js +16 -14
  144. package/core/renderers/measurables/output_connection.js +26 -20
  145. package/core/renderers/measurables/previous_connection.js +16 -15
  146. package/core/renderers/measurables/round_corner.js +20 -18
  147. package/core/renderers/measurables/row.js +184 -168
  148. package/core/renderers/measurables/spacer_row.js +38 -23
  149. package/core/renderers/measurables/square_corner.js +18 -16
  150. package/core/renderers/measurables/statement_input.js +23 -20
  151. package/core/renderers/measurables/top_row.js +88 -85
  152. package/core/renderers/minimalist/constants.js +8 -7
  153. package/core/renderers/minimalist/drawer.js +11 -10
  154. package/core/renderers/minimalist/info.js +18 -18
  155. package/core/renderers/minimalist/renderer.js +40 -39
  156. package/core/renderers/thrasos/info.js +258 -248
  157. package/core/renderers/thrasos/renderer.js +20 -20
  158. package/core/renderers/zelos/constants.js +898 -873
  159. package/core/renderers/zelos/drawer.js +186 -169
  160. package/core/renderers/zelos/info.js +502 -479
  161. package/core/renderers/zelos/marker_svg.js +129 -115
  162. package/core/renderers/zelos/measurables/bottom_row.js +31 -30
  163. package/core/renderers/zelos/measurables/inputs.js +22 -21
  164. package/core/renderers/zelos/measurables/row_elements.js +14 -13
  165. package/core/renderers/zelos/measurables/top_row.js +34 -33
  166. package/core/renderers/zelos/path_object.js +181 -180
  167. package/core/renderers/zelos/renderer.js +91 -92
  168. package/core/scrollbar.js +759 -713
  169. package/core/scrollbar_pair.js +250 -245
  170. package/core/serialization/blocks.js +26 -10
  171. package/core/serialization/workspaces.js +3 -2
  172. package/core/shortcut_registry.js +286 -277
  173. package/core/sprites.js +31 -0
  174. package/core/theme.js +135 -141
  175. package/core/theme_manager.js +147 -143
  176. package/core/toolbox/category.js +602 -576
  177. package/core/toolbox/collapsible_category.js +226 -227
  178. package/core/toolbox/separator.js +70 -61
  179. package/core/toolbox/toolbox.js +934 -927
  180. package/core/toolbox/toolbox_item.js +115 -99
  181. package/core/tooltip.js +108 -35
  182. package/core/touch.js +8 -3
  183. package/core/touch_gesture.js +254 -251
  184. package/core/trashcan.js +606 -595
  185. package/core/utils/coordinate.js +97 -95
  186. package/core/utils/dom.js +2 -2
  187. package/core/utils/global.js +2 -0
  188. package/core/utils/rect.js +41 -37
  189. package/core/utils/sentinel.js +25 -0
  190. package/core/utils/size.js +30 -27
  191. package/core/utils/svg.js +18 -16
  192. package/core/variable_map.js +325 -341
  193. package/core/variable_model.js +55 -54
  194. package/core/variables.js +9 -2
  195. package/core/variables_dynamic.js +3 -1
  196. package/core/warning.js +126 -120
  197. package/core/widgetdiv.js +4 -4
  198. package/core/workspace.js +685 -664
  199. package/core/workspace_audio.js +124 -118
  200. package/core/workspace_comment.js +308 -298
  201. package/core/workspace_comment_svg.js +1029 -951
  202. package/core/workspace_drag_surface_svg.js +147 -140
  203. package/core/workspace_dragger.js +70 -71
  204. package/core/workspace_svg.js +2322 -2297
  205. package/core/xml.js +30 -20
  206. package/core/zoom_controls.js +431 -439
  207. package/generators/dart/colour.js +56 -64
  208. package/generators/dart/lists.js +61 -50
  209. package/generators/dart/math.js +160 -148
  210. package/generators/dart/text.js +83 -61
  211. package/generators/javascript/colour.js +37 -34
  212. package/generators/javascript/lists.js +50 -43
  213. package/generators/javascript/math.js +123 -139
  214. package/generators/javascript/text.js +67 -81
  215. package/generators/lua/colour.js +25 -23
  216. package/generators/lua/lists.js +97 -69
  217. package/generators/lua/logic.js +1 -2
  218. package/generators/lua/math.js +182 -144
  219. package/generators/lua/text.js +116 -99
  220. package/generators/php/colour.js +38 -32
  221. package/generators/php/lists.js +109 -89
  222. package/generators/php/math.js +90 -81
  223. package/generators/php/text.js +63 -61
  224. package/generators/python/colour.js +18 -18
  225. package/generators/python/lists.js +38 -30
  226. package/generators/python/loops.js +12 -8
  227. package/generators/python/math.js +104 -106
  228. package/generators/python/text.js +34 -30
  229. package/msg/smn.js +436 -0
  230. package/package.json +7 -6
  231. package/blocks/all.js +0 -23
@@ -17,9 +17,12 @@
17
17
  */
18
18
  goog.module('Blockly.geras.RenderInfo');
19
19
 
20
- const object = goog.require('Blockly.utils.object');
21
20
  /* eslint-disable-next-line no-unused-vars */
22
21
  const {BlockSvg} = goog.requireType('Blockly.BlockSvg');
22
+ /* eslint-disable-next-line no-unused-vars */
23
+ const {BottomRow} = goog.requireType('Blockly.blockRendering.BottomRow');
24
+ /* eslint-disable-next-line no-unused-vars */
25
+ const {ConstantProvider} = goog.requireType('Blockly.geras.ConstantProvider');
23
26
  const {ExternalValueInput} = goog.require('Blockly.blockRendering.ExternalValueInput');
24
27
  /* eslint-disable-next-line no-unused-vars */
25
28
  const {Field} = goog.requireType('Blockly.blockRendering.Field');
@@ -31,6 +34,8 @@ const {RenderInfo: BaseRenderInfo} = goog.require('Blockly.blockRendering.Render
31
34
  /* eslint-disable-next-line no-unused-vars */
32
35
  const {Renderer} = goog.requireType('Blockly.geras.Renderer');
33
36
  const {StatementInput} = goog.require('Blockly.geras.StatementInput');
37
+ /* eslint-disable-next-line no-unused-vars */
38
+ const {TopRow} = goog.requireType('Blockly.blockRendering.TopRow');
34
39
  const {Types} = goog.require('Blockly.blockRendering.Types');
35
40
  const {inputTypes} = goog.require('Blockly.inputTypes');
36
41
 
@@ -41,425 +46,443 @@ const {inputTypes} = goog.require('Blockly.inputTypes');
41
46
  * This measure pass does not propagate changes to the block (although fields
42
47
  * may choose to rerender when getSize() is called). However, calling it
43
48
  * repeatedly may be expensive.
44
- *
45
- * @param {!Renderer} renderer The renderer in use.
46
- * @param {!BlockSvg} block The block to measure.
47
- * @constructor
48
- * @package
49
49
  * @extends {BaseRenderInfo}
50
50
  * @alias Blockly.geras.RenderInfo
51
51
  */
52
- const RenderInfo = function(renderer, block) {
53
- RenderInfo.superClass_.constructor.call(this, renderer, block);
54
- };
55
- object.inherits(RenderInfo, BaseRenderInfo);
56
-
57
- /**
58
- * Get the block renderer in use.
59
- * @return {!Renderer} The block renderer in use.
60
- * @package
61
- */
62
- RenderInfo.prototype.getRenderer = function() {
63
- return /** @type {!Renderer} */ (this.renderer_);
64
- };
65
-
66
- /**
67
- * @override
68
- */
69
- RenderInfo.prototype.populateBottomRow_ = function() {
70
- RenderInfo.superClass_.populateBottomRow_.call(this);
71
-
72
- const followsStatement = this.block_.inputList.length &&
73
- this.block_.inputList[this.block_.inputList.length - 1].type ===
74
- inputTypes.STATEMENT;
75
-
76
- // The minimum height of the bottom row is smaller in Geras than in other
77
- // renderers, because the dark path adds a pixel.
78
- // If one of the row's elements has a greater height this will be overwritten
79
- // in the compute pass.
80
- if (!followsStatement) {
81
- this.bottomRow.minHeight =
82
- this.constants_.MEDIUM_PADDING - this.constants_.DARK_PATH_OFFSET;
52
+ class RenderInfo extends BaseRenderInfo {
53
+ /**
54
+ * @param {!Renderer} renderer The renderer in use.
55
+ * @param {!BlockSvg} block The block to measure.
56
+ * @package
57
+ */
58
+ constructor(renderer, block) {
59
+ super(renderer, block);
60
+
61
+ /** @type {!ConstantProvider} */
62
+ this.constants_;
63
+ }
64
+
65
+ /**
66
+ * Get the block renderer in use.
67
+ * @return {!Renderer} The block renderer in use.
68
+ * @package
69
+ */
70
+ getRenderer() {
71
+ return /** @type {!Renderer} */ (this.renderer_);
72
+ }
73
+
74
+ /**
75
+ * @override
76
+ */
77
+ populateBottomRow_() {
78
+ super.populateBottomRow_();
79
+
80
+ const followsStatement = this.block_.inputList.length &&
81
+ this.block_.inputList[this.block_.inputList.length - 1].type ===
82
+ inputTypes.STATEMENT;
83
+
84
+ // The minimum height of the bottom row is smaller in Geras than in other
85
+ // renderers, because the dark path adds a pixel.
86
+ // If one of the row's elements has a greater height this will be
87
+ // overwritten in the compute pass.
88
+ if (!followsStatement) {
89
+ this.bottomRow.minHeight =
90
+ this.constants_.MEDIUM_PADDING - this.constants_.DARK_PATH_OFFSET;
91
+ }
83
92
  }
84
- };
85
93
 
86
- /**
87
- * @override
88
- */
89
- RenderInfo.prototype.addInput_ = function(input, activeRow) {
90
- // Non-dummy inputs have visual representations onscreen.
91
- if (this.isInline && input.type === inputTypes.VALUE) {
92
- activeRow.elements.push(new InlineInput(this.constants_, input));
93
- activeRow.hasInlineInput = true;
94
- } else if (input.type === inputTypes.STATEMENT) {
95
- activeRow.elements.push(new StatementInput(this.constants_, input));
96
- activeRow.hasStatement = true;
97
- } else if (input.type === inputTypes.VALUE) {
98
- activeRow.elements.push(new ExternalValueInput(this.constants_, input));
99
- activeRow.hasExternalInput = true;
100
- } else if (input.type === inputTypes.DUMMY) {
101
- // Dummy inputs have no visual representation, but the information is still
102
- // important.
103
- activeRow.minHeight =
104
- Math.max(activeRow.minHeight, this.constants_.DUMMY_INPUT_MIN_HEIGHT);
105
- activeRow.hasDummyInput = true;
106
- }
107
- // Ignore row alignment if inline.
108
- if (!this.isInline && activeRow.align === null) {
109
- activeRow.align = input.align;
94
+ /**
95
+ * @override
96
+ */
97
+ addInput_(input, activeRow) {
98
+ // Non-dummy inputs have visual representations onscreen.
99
+ if (this.isInline && input.type === inputTypes.VALUE) {
100
+ activeRow.elements.push(new InlineInput(this.constants_, input));
101
+ activeRow.hasInlineInput = true;
102
+ } else if (input.type === inputTypes.STATEMENT) {
103
+ activeRow.elements.push(new StatementInput(this.constants_, input));
104
+ activeRow.hasStatement = true;
105
+ } else if (input.type === inputTypes.VALUE) {
106
+ activeRow.elements.push(new ExternalValueInput(this.constants_, input));
107
+ activeRow.hasExternalInput = true;
108
+ } else if (input.type === inputTypes.DUMMY) {
109
+ // Dummy inputs have no visual representation, but the information is
110
+ // still important.
111
+ activeRow.minHeight =
112
+ Math.max(activeRow.minHeight, this.constants_.DUMMY_INPUT_MIN_HEIGHT);
113
+ activeRow.hasDummyInput = true;
114
+ }
115
+ // Ignore row alignment if inline.
116
+ if (!this.isInline && activeRow.align === null) {
117
+ activeRow.align = input.align;
118
+ }
110
119
  }
111
- };
112
120
 
113
- /**
114
- * @override
115
- */
116
- RenderInfo.prototype.addElemSpacing_ = function() {
117
- let hasExternalInputs = false;
118
- for (let i = 0, row; (row = this.rows[i]); i++) {
119
- if (row.hasExternalInput) {
120
- hasExternalInputs = true;
121
+ /**
122
+ * @override
123
+ */
124
+ addElemSpacing_() {
125
+ let hasExternalInputs = false;
126
+ for (let i = 0, row; (row = this.rows[i]); i++) {
127
+ if (row.hasExternalInput) {
128
+ hasExternalInputs = true;
129
+ }
121
130
  }
122
- }
123
- for (let i = 0, row; (row = this.rows[i]); i++) {
124
- const oldElems = row.elements;
125
- row.elements = [];
126
- // No spacing needed before the corner on the top row or the bottom row.
127
- if (row.startsWithElemSpacer()) {
128
- // There's a spacer before the first element in the row.
129
- row.elements.push(new InRowSpacer(
130
- this.constants_, this.getInRowSpacing_(null, oldElems[0])));
131
- }
132
- if (!oldElems.length) {
133
- continue;
134
- }
135
- for (let e = 0; e < oldElems.length - 1; e++) {
136
- row.elements.push(oldElems[e]);
137
- const spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]);
138
- row.elements.push(new InRowSpacer(this.constants_, spacing));
139
- }
140
- row.elements.push(oldElems[oldElems.length - 1]);
141
- if (row.endsWithElemSpacer()) {
142
- let spacing = this.getInRowSpacing_(oldElems[oldElems.length - 1], null);
143
- if (hasExternalInputs && row.hasDummyInput) {
144
- spacing += this.constants_.TAB_WIDTH;
131
+ for (let i = 0, row; (row = this.rows[i]); i++) {
132
+ const oldElems = row.elements;
133
+ row.elements = [];
134
+ // No spacing needed before the corner on the top row or the bottom row.
135
+ if (row.startsWithElemSpacer()) {
136
+ // There's a spacer before the first element in the row.
137
+ row.elements.push(new InRowSpacer(
138
+ this.constants_, this.getInRowSpacing_(null, oldElems[0])));
139
+ }
140
+ if (!oldElems.length) {
141
+ continue;
142
+ }
143
+ for (let e = 0; e < oldElems.length - 1; e++) {
144
+ row.elements.push(oldElems[e]);
145
+ const spacing = this.getInRowSpacing_(oldElems[e], oldElems[e + 1]);
146
+ row.elements.push(new InRowSpacer(this.constants_, spacing));
147
+ }
148
+ row.elements.push(oldElems[oldElems.length - 1]);
149
+ if (row.endsWithElemSpacer()) {
150
+ let spacing =
151
+ this.getInRowSpacing_(oldElems[oldElems.length - 1], null);
152
+ if (hasExternalInputs && row.hasDummyInput) {
153
+ spacing += this.constants_.TAB_WIDTH;
154
+ }
155
+ // There's a spacer after the last element in the row.
156
+ row.elements.push(new InRowSpacer(this.constants_, spacing));
145
157
  }
146
- // There's a spacer after the last element in the row.
147
- row.elements.push(new InRowSpacer(this.constants_, spacing));
148
158
  }
149
159
  }
150
- };
151
-
152
- /**
153
- * @override
154
- */
155
- RenderInfo.prototype.getInRowSpacing_ = function(prev, next) {
156
- if (!prev) {
157
- // Between an editable field and the beginning of the row.
158
- if (next && Types.isField(next) &&
159
- (/** @type {Field} */ (next)).isEditable) {
160
- return this.constants_.MEDIUM_PADDING;
161
- }
162
- // Inline input at the beginning of the row.
163
- if (next && Types.isInlineInput(next)) {
164
- return this.constants_.MEDIUM_LARGE_PADDING;
165
- }
166
- if (next && Types.isStatementInput(next)) {
167
- return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
168
- }
169
- // Anything else at the beginning of the row.
170
- return this.constants_.LARGE_PADDING;
171
- }
172
160
 
173
- // Spacing between a non-input and the end of the row or a statement input.
174
- if (!Types.isInput(prev) && (!next || Types.isStatementInput(next))) {
175
- // Between an editable field and the end of the row.
176
- if (Types.isField(prev) && (/** @type {Field} */ (prev)).isEditable) {
177
- return this.constants_.MEDIUM_PADDING;
178
- }
179
- // Padding at the end of an icon-only row to make the block shape clearer.
180
- if (Types.isIcon(prev)) {
181
- return (this.constants_.LARGE_PADDING * 2) + 1;
182
- }
183
- if (Types.isHat(prev)) {
184
- return this.constants_.NO_PADDING;
185
- }
186
- // Establish a minimum width for a block with a previous or next connection.
187
- if (Types.isPreviousOrNextConnection(prev)) {
161
+ /**
162
+ * @override
163
+ */
164
+ getInRowSpacing_(prev, next) {
165
+ if (!prev) {
166
+ // Between an editable field and the beginning of the row.
167
+ if (next && Types.isField(next) &&
168
+ (/** @type {Field} */ (next)).isEditable) {
169
+ return this.constants_.MEDIUM_PADDING;
170
+ }
171
+ // Inline input at the beginning of the row.
172
+ if (next && Types.isInlineInput(next)) {
173
+ return this.constants_.MEDIUM_LARGE_PADDING;
174
+ }
175
+ if (next && Types.isStatementInput(next)) {
176
+ return this.constants_.STATEMENT_INPUT_PADDING_LEFT;
177
+ }
178
+ // Anything else at the beginning of the row.
188
179
  return this.constants_.LARGE_PADDING;
189
180
  }
190
- // Between rounded corner and the end of the row.
191
- if (Types.isLeftRoundedCorner(prev)) {
192
- return this.constants_.MIN_BLOCK_WIDTH;
193
- }
194
- // Between a jagged edge and the end of the row.
195
- if (Types.isJaggedEdge(prev)) {
196
- return this.constants_.NO_PADDING;
197
- }
198
- // Between noneditable fields and icons and the end of the row.
199
- return this.constants_.LARGE_PADDING;
200
- }
201
181
 
202
- // Between inputs and the end of the row.
203
- if (Types.isInput(prev) && !next) {
204
- if (Types.isExternalInput(prev)) {
205
- return this.constants_.NO_PADDING;
206
- } else if (Types.isInlineInput(prev)) {
182
+ // Spacing between a non-input and the end of the row or a statement input.
183
+ if (!Types.isInput(prev) && (!next || Types.isStatementInput(next))) {
184
+ // Between an editable field and the end of the row.
185
+ if (Types.isField(prev) && (/** @type {Field} */ (prev)).isEditable) {
186
+ return this.constants_.MEDIUM_PADDING;
187
+ }
188
+ // Padding at the end of an icon-only row to make the block shape clearer.
189
+ if (Types.isIcon(prev)) {
190
+ return (this.constants_.LARGE_PADDING * 2) + 1;
191
+ }
192
+ if (Types.isHat(prev)) {
193
+ return this.constants_.NO_PADDING;
194
+ }
195
+ // Establish a minimum width for a block with a previous or next
196
+ // connection.
197
+ if (Types.isPreviousOrNextConnection(prev)) {
198
+ return this.constants_.LARGE_PADDING;
199
+ }
200
+ // Between rounded corner and the end of the row.
201
+ if (Types.isLeftRoundedCorner(prev)) {
202
+ return this.constants_.MIN_BLOCK_WIDTH;
203
+ }
204
+ // Between a jagged edge and the end of the row.
205
+ if (Types.isJaggedEdge(prev)) {
206
+ return this.constants_.NO_PADDING;
207
+ }
208
+ // Between noneditable fields and icons and the end of the row.
207
209
  return this.constants_.LARGE_PADDING;
208
- } else if (Types.isStatementInput(prev)) {
209
- return this.constants_.NO_PADDING;
210
210
  }
211
- }
212
211
 
213
- // Spacing between a non-input and an input.
214
- if (!Types.isInput(prev) && next && Types.isInput(next)) {
215
- // Between an editable field and an input.
216
- if (Types.isField(prev) && (/** @type {Field} */ (prev)).isEditable) {
217
- if (Types.isInlineInput(next)) {
218
- return this.constants_.SMALL_PADDING;
219
- } else if (Types.isExternalInput(next)) {
220
- return this.constants_.SMALL_PADDING;
221
- }
222
- } else {
223
- if (Types.isInlineInput(next)) {
224
- return this.constants_.MEDIUM_LARGE_PADDING;
225
- } else if (Types.isExternalInput(next)) {
226
- return this.constants_.MEDIUM_LARGE_PADDING;
227
- } else if (Types.isStatementInput(next)) {
212
+ // Between inputs and the end of the row.
213
+ if (Types.isInput(prev) && !next) {
214
+ if (Types.isExternalInput(prev)) {
215
+ return this.constants_.NO_PADDING;
216
+ } else if (Types.isInlineInput(prev)) {
228
217
  return this.constants_.LARGE_PADDING;
218
+ } else if (Types.isStatementInput(prev)) {
219
+ return this.constants_.NO_PADDING;
229
220
  }
230
221
  }
231
- return this.constants_.LARGE_PADDING - 1;
232
- }
233
222
 
234
- // Spacing between an icon and an icon or field.
235
- if (Types.isIcon(prev) && next && !Types.isInput(next)) {
236
- return this.constants_.LARGE_PADDING;
237
- }
223
+ // Spacing between a non-input and an input.
224
+ if (!Types.isInput(prev) && next && Types.isInput(next)) {
225
+ // Between an editable field and an input.
226
+ if (Types.isField(prev) && (/** @type {Field} */ (prev)).isEditable) {
227
+ if (Types.isInlineInput(next)) {
228
+ return this.constants_.SMALL_PADDING;
229
+ } else if (Types.isExternalInput(next)) {
230
+ return this.constants_.SMALL_PADDING;
231
+ }
232
+ } else {
233
+ if (Types.isInlineInput(next)) {
234
+ return this.constants_.MEDIUM_LARGE_PADDING;
235
+ } else if (Types.isExternalInput(next)) {
236
+ return this.constants_.MEDIUM_LARGE_PADDING;
237
+ } else if (Types.isStatementInput(next)) {
238
+ return this.constants_.LARGE_PADDING;
239
+ }
240
+ }
241
+ return this.constants_.LARGE_PADDING - 1;
242
+ }
238
243
 
239
- // Spacing between an inline input and a field.
240
- if (Types.isInlineInput(prev) && next && Types.isField(next)) {
241
- // Editable field after inline input.
242
- if ((/** @type {Field} */ (next)).isEditable) {
243
- return this.constants_.MEDIUM_PADDING;
244
- } else {
245
- // Noneditable field after inline input.
244
+ // Spacing between an icon and an icon or field.
245
+ if (Types.isIcon(prev) && next && !Types.isInput(next)) {
246
246
  return this.constants_.LARGE_PADDING;
247
247
  }
248
- }
249
248
 
250
- if (Types.isLeftSquareCorner(prev) && next) {
251
- // Spacing between a hat and a corner
252
- if (Types.isHat(next)) {
253
- return this.constants_.NO_PADDING;
254
- }
255
- // Spacing between a square corner and a previous or next connection
256
- if (Types.isPreviousConnection(next)) {
257
- return next.notchOffset;
258
- } else if (Types.isNextConnection(next)) {
259
- // Next connections are shifted slightly to the left (in both LTR and RTL)
260
- // to make the dark path under the previous connection show through.
261
- const offset = (this.RTL ? 1 : -1) * this.constants_.DARK_PATH_OFFSET / 2;
262
- return next.notchOffset + offset;
249
+ // Spacing between an inline input and a field.
250
+ if (Types.isInlineInput(prev) && next && Types.isField(next)) {
251
+ // Editable field after inline input.
252
+ if ((/** @type {Field} */ (next)).isEditable) {
253
+ return this.constants_.MEDIUM_PADDING;
254
+ } else {
255
+ // Noneditable field after inline input.
256
+ return this.constants_.LARGE_PADDING;
257
+ }
263
258
  }
264
- }
265
259
 
266
- // Spacing between a rounded corner and a previous or next connection.
267
- if (Types.isLeftRoundedCorner(prev) && next) {
268
- if (Types.isPreviousConnection(next)) {
269
- return next.notchOffset - this.constants_.CORNER_RADIUS;
270
- } else if (Types.isNextConnection(next)) {
271
- // Next connections are shifted slightly to the left (in both LTR and RTL)
272
- // to make the dark path under the previous connection show through.
273
- const offset = (this.RTL ? 1 : -1) * this.constants_.DARK_PATH_OFFSET / 2;
274
- return next.notchOffset - this.constants_.CORNER_RADIUS + offset;
260
+ if (Types.isLeftSquareCorner(prev) && next) {
261
+ // Spacing between a hat and a corner
262
+ if (Types.isHat(next)) {
263
+ return this.constants_.NO_PADDING;
264
+ }
265
+ // Spacing between a square corner and a previous or next connection
266
+ if (Types.isPreviousConnection(next)) {
267
+ return next.notchOffset;
268
+ } else if (Types.isNextConnection(next)) {
269
+ // Next connections are shifted slightly to the left (in both LTR and
270
+ // RTL) to make the dark path under the previous connection show
271
+ // through.
272
+ const offset =
273
+ (this.RTL ? 1 : -1) * this.constants_.DARK_PATH_OFFSET / 2;
274
+ return next.notchOffset + offset;
275
+ }
275
276
  }
276
- }
277
277
 
278
- // Spacing between two fields of the same editability.
279
- if (Types.isField(prev) && next && Types.isField(next) &&
280
- ((/** @type {Field} */ (prev)).isEditable ===
281
- (/** @type {Field} */ (next)).isEditable)) {
282
- return this.constants_.LARGE_PADDING;
283
- }
278
+ // Spacing between a rounded corner and a previous or next connection.
279
+ if (Types.isLeftRoundedCorner(prev) && next) {
280
+ if (Types.isPreviousConnection(next)) {
281
+ return next.notchOffset - this.constants_.CORNER_RADIUS;
282
+ } else if (Types.isNextConnection(next)) {
283
+ // Next connections are shifted slightly to the left (in both LTR and
284
+ // RTL) to make the dark path under the previous connection show
285
+ // through.
286
+ const offset =
287
+ (this.RTL ? 1 : -1) * this.constants_.DARK_PATH_OFFSET / 2;
288
+ return next.notchOffset - this.constants_.CORNER_RADIUS + offset;
289
+ }
290
+ }
284
291
 
285
- // Spacing between anything and a jagged edge.
286
- if (next && Types.isJaggedEdge(next)) {
287
- return this.constants_.LARGE_PADDING;
288
- }
292
+ // Spacing between two fields of the same editability.
293
+ if (Types.isField(prev) && next && Types.isField(next) &&
294
+ ((/** @type {Field} */ (prev)).isEditable ===
295
+ (/** @type {Field} */ (next)).isEditable)) {
296
+ return this.constants_.LARGE_PADDING;
297
+ }
289
298
 
290
- return this.constants_.MEDIUM_PADDING;
291
- };
299
+ // Spacing between anything and a jagged edge.
300
+ if (next && Types.isJaggedEdge(next)) {
301
+ return this.constants_.LARGE_PADDING;
302
+ }
292
303
 
293
- /**
294
- * @override
295
- */
296
- RenderInfo.prototype.getSpacerRowHeight_ = function(prev, next) {
297
- // If we have an empty block add a spacer to increase the height.
298
- if (Types.isTopRow(prev) && Types.isBottomRow(next)) {
299
- return this.constants_.EMPTY_BLOCK_SPACER_HEIGHT;
300
- }
301
- // Top and bottom rows act as a spacer so we don't need any extra padding.
302
- if (Types.isTopRow(prev) || Types.isBottomRow(next)) {
303
- return this.constants_.NO_PADDING;
304
+ return this.constants_.MEDIUM_PADDING;
304
305
  }
305
- if (prev.hasExternalInput && next.hasExternalInput) {
306
- return this.constants_.LARGE_PADDING;
307
- }
308
- if (!prev.hasStatement && next.hasStatement) {
309
- return this.constants_.BETWEEN_STATEMENT_PADDING_Y;
310
- }
311
- if (prev.hasStatement && next.hasStatement) {
312
- return this.constants_.LARGE_PADDING;
313
- }
314
- if (!prev.hasStatement && next.hasDummyInput) {
315
- return this.constants_.LARGE_PADDING;
316
- }
317
- if (prev.hasDummyInput) {
318
- return this.constants_.LARGE_PADDING;
319
- }
320
- return this.constants_.MEDIUM_PADDING;
321
- };
322
306
 
323
- /**
324
- * @override
325
- */
326
- RenderInfo.prototype.getElemCenterline_ = function(row, elem) {
327
- if (Types.isSpacer(elem)) {
328
- return row.yPos + elem.height / 2;
329
- }
330
- if (Types.isBottomRow(row)) {
331
- const baseline = row.yPos + row.height - row.descenderHeight;
332
- if (Types.isNextConnection(elem)) {
333
- return baseline + elem.height / 2;
307
+ /**
308
+ * @override
309
+ */
310
+ getSpacerRowHeight_(prev, next) {
311
+ // If we have an empty block add a spacer to increase the height.
312
+ if (Types.isTopRow(prev) && Types.isBottomRow(next)) {
313
+ return this.constants_.EMPTY_BLOCK_SPACER_HEIGHT;
334
314
  }
335
- return baseline - elem.height / 2;
336
- }
337
- if (Types.isTopRow(row)) {
338
- if (Types.isHat(elem)) {
339
- return row.capline - elem.height / 2;
315
+ // Top and bottom rows act as a spacer so we don't need any extra padding.
316
+ if (Types.isTopRow(prev) || Types.isBottomRow(next)) {
317
+ return this.constants_.NO_PADDING;
318
+ }
319
+ if (prev.hasExternalInput && next.hasExternalInput) {
320
+ return this.constants_.LARGE_PADDING;
321
+ }
322
+ if (!prev.hasStatement && next.hasStatement) {
323
+ return this.constants_.BETWEEN_STATEMENT_PADDING_Y;
324
+ }
325
+ if (prev.hasStatement && next.hasStatement) {
326
+ return this.constants_.LARGE_PADDING;
327
+ }
328
+ if (!prev.hasStatement && next.hasDummyInput) {
329
+ return this.constants_.LARGE_PADDING;
330
+ }
331
+ if (prev.hasDummyInput) {
332
+ return this.constants_.LARGE_PADDING;
340
333
  }
341
- return row.capline + elem.height / 2;
334
+ return this.constants_.MEDIUM_PADDING;
342
335
  }
343
336
 
344
- let result = row.yPos;
345
- if (Types.isField(elem) || Types.isIcon(elem)) {
346
- result += (elem.height / 2);
347
- if ((row.hasInlineInput || row.hasStatement) &&
348
- elem.height + this.constants_.TALL_INPUT_FIELD_OFFSET_Y <= row.height) {
349
- result += this.constants_.TALL_INPUT_FIELD_OFFSET_Y;
350
- }
351
- } else if (Types.isInlineInput(elem)) {
352
- result += elem.height / 2;
353
- } else {
354
- result += (row.height / 2);
355
- }
356
- return result;
357
- };
337
+ /**
338
+ * @override
339
+ */
340
+ getElemCenterline_(row, elem) {
341
+ if (Types.isSpacer(elem)) {
342
+ return row.yPos + elem.height / 2;
343
+ }
344
+ if (Types.isBottomRow(row)) {
345
+ const bottomRow = /** @type {!BottomRow} */ (row);
346
+ const baseline =
347
+ bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
348
+ if (Types.isNextConnection(elem)) {
349
+ return baseline + elem.height / 2;
350
+ }
351
+ return baseline - elem.height / 2;
352
+ }
353
+ if (Types.isTopRow(row)) {
354
+ const topRow = /** @type {!TopRow} */ (row);
355
+ if (Types.isHat(elem)) {
356
+ return topRow.capline - elem.height / 2;
357
+ }
358
+ return topRow.capline + elem.height / 2;
359
+ }
358
360
 
359
- /**
360
- * @override
361
- */
362
- RenderInfo.prototype.alignRowElements_ = function() {
363
- if (!this.isInline) {
364
- RenderInfo.superClass_.alignRowElements_.call(this);
365
- return;
361
+ let result = row.yPos;
362
+ if (Types.isField(elem) || Types.isIcon(elem)) {
363
+ result += (elem.height / 2);
364
+ if ((row.hasInlineInput || row.hasStatement) &&
365
+ elem.height + this.constants_.TALL_INPUT_FIELD_OFFSET_Y <=
366
+ row.height) {
367
+ result += this.constants_.TALL_INPUT_FIELD_OFFSET_Y;
368
+ }
369
+ } else if (Types.isInlineInput(elem)) {
370
+ result += elem.height / 2;
371
+ } else {
372
+ result += (row.height / 2);
373
+ }
374
+ return result;
366
375
  }
367
376
 
368
- // Walk backgrounds through rows on the block, keeping track of the right
369
- // input edge.
370
- let nextRightEdge = 0;
371
- let prevInput = null;
372
- for (let i = this.rows.length - 1, row; (row = this.rows[i]); i--) {
373
- row.nextRightEdge = nextRightEdge;
374
- if (Types.isInputRow(row)) {
375
- if (row.hasStatement) {
376
- this.alignStatementRow_(
377
- /** @type {!InputRow} */ (row));
377
+ /**
378
+ * @override
379
+ */
380
+ alignRowElements_() {
381
+ if (!this.isInline) {
382
+ super.alignRowElements_();
383
+ return;
384
+ }
385
+
386
+ // Walk backgrounds through rows on the block, keeping track of the right
387
+ // input edge.
388
+ let nextRightEdge = 0;
389
+ const rowNextRightEdges = new WeakMap();
390
+ let prevInput = null;
391
+ for (let i = this.rows.length - 1, row; (row = this.rows[i]); i--) {
392
+ rowNextRightEdges.set(row, nextRightEdge);
393
+ if (Types.isInputRow(row)) {
394
+ if (row.hasStatement) {
395
+ this.alignStatementRow_(
396
+ /** @type {!InputRow} */ (row));
397
+ }
398
+ if (prevInput && prevInput.hasStatement &&
399
+ row.width < prevInput.width) {
400
+ rowNextRightEdges.set(row, prevInput.width);
401
+ } else {
402
+ nextRightEdge = row.width;
403
+ }
404
+ prevInput = row;
378
405
  }
379
- if (prevInput && prevInput.hasStatement && row.width < prevInput.width) {
380
- row.nextRightEdge = prevInput.width;
406
+ }
407
+ // Walk down each row from the top, comparing the prev and next right input
408
+ // edges and setting the desired width to the max of the two.
409
+ let prevRightEdge = 0;
410
+ for (let i = 0, row; (row = this.rows[i]); i++) {
411
+ if (row.hasStatement) {
412
+ prevRightEdge = this.getDesiredRowWidth_(row);
413
+ } else if (Types.isSpacer(row)) {
414
+ // Set the spacer row to the max of the prev or next input width.
415
+ row.width = Math.max(prevRightEdge, rowNextRightEdges.get(row));
381
416
  } else {
382
- nextRightEdge = row.width;
417
+ const currentWidth = row.width;
418
+ const desiredWidth =
419
+ Math.max(prevRightEdge, rowNextRightEdges.get(row));
420
+ const missingSpace = desiredWidth - currentWidth;
421
+ if (missingSpace > 0) {
422
+ this.addAlignmentPadding_(row, missingSpace);
423
+ }
424
+ prevRightEdge = row.width;
383
425
  }
384
- prevInput = row;
385
426
  }
386
427
  }
387
- // Walk down each row from the top, comparing the prev and next right input
388
- // edges and setting the desired width to the max of the two.
389
- let prevRightEdge = 0;
390
- for (let i = 0, row; (row = this.rows[i]); i++) {
391
- if (row.hasStatement) {
392
- prevRightEdge = this.getDesiredRowWidth_(row);
393
- } else if (Types.isSpacer(row)) {
394
- // Set the spacer row to the max of the prev or next input width.
395
- row.width = Math.max(prevRightEdge, row.nextRightEdge);
396
- } else {
397
- const currentWidth = row.width;
398
- const desiredWidth = Math.max(prevRightEdge, row.nextRightEdge);
399
- const missingSpace = desiredWidth - currentWidth;
400
- if (missingSpace > 0) {
401
- this.addAlignmentPadding_(row, missingSpace);
428
+
429
+ /**
430
+ * @override
431
+ */
432
+ getDesiredRowWidth_(row) {
433
+ // Limit the width of a statement row when a block is inline.
434
+ if (this.isInline && row.hasStatement) {
435
+ return this.statementEdge + this.constants_.MAX_BOTTOM_WIDTH +
436
+ this.startX;
437
+ }
438
+ return super.getDesiredRowWidth_(row);
439
+ }
440
+
441
+ /**
442
+ * @override
443
+ */
444
+ finalize_() {
445
+ // Performance note: this could be combined with the draw pass, if the time
446
+ // that this takes is excessive. But it shouldn't be, because it only
447
+ // accesses and sets properties that already exist on the objects.
448
+ let widestRowWithConnectedBlocks = 0;
449
+ let yCursor = 0;
450
+ for (let i = 0, row; (row = this.rows[i]); i++) {
451
+ row.yPos = yCursor;
452
+ row.xPos = this.startX;
453
+ yCursor += row.height;
454
+
455
+ widestRowWithConnectedBlocks =
456
+ Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
457
+ // Add padding to the bottom row if block height is less than minimum
458
+ const heightWithoutHat = yCursor - this.topRow.ascenderHeight;
459
+ if (row === this.bottomRow &&
460
+ heightWithoutHat < this.constants_.MIN_BLOCK_HEIGHT) {
461
+ // But the hat height shouldn't be part of this.
462
+ const diff = this.constants_.MIN_BLOCK_HEIGHT - heightWithoutHat;
463
+ this.bottomRow.height += diff;
464
+ yCursor += diff;
402
465
  }
403
- prevRightEdge = row.width;
466
+ this.recordElemPositions_(row);
467
+ }
468
+ if (this.outputConnection && this.block_.nextConnection &&
469
+ this.block_.nextConnection.isConnected()) {
470
+ // Include width of connected block in value to stack width measurement.
471
+ widestRowWithConnectedBlocks = Math.max(
472
+ widestRowWithConnectedBlocks,
473
+ this.block_.nextConnection.targetBlock().getHeightWidth().width -
474
+ this.constants_.DARK_PATH_OFFSET);
404
475
  }
405
- }
406
- };
407
476
 
408
- /**
409
- * @override
410
- */
411
- RenderInfo.prototype.getDesiredRowWidth_ = function(row) {
412
- // Limit the width of a statement row when a block is inline.
413
- if (this.isInline && row.hasStatement) {
414
- return this.statementEdge + this.constants_.MAX_BOTTOM_WIDTH + this.startX;
415
- }
416
- return RenderInfo.superClass_.getDesiredRowWidth_.call(this, row);
417
- };
477
+ this.bottomRow.baseline = yCursor - this.bottomRow.descenderHeight;
418
478
 
419
- /**
420
- * @override
421
- */
422
- RenderInfo.prototype.finalize_ = function() {
423
- // Performance note: this could be combined with the draw pass, if the time
424
- // that this takes is excessive. But it shouldn't be, because it only
425
- // accesses and sets properties that already exist on the objects.
426
- let widestRowWithConnectedBlocks = 0;
427
- let yCursor = 0;
428
- for (let i = 0, row; (row = this.rows[i]); i++) {
429
- row.yPos = yCursor;
430
- row.xPos = this.startX;
431
- yCursor += row.height;
432
-
433
- widestRowWithConnectedBlocks =
434
- Math.max(widestRowWithConnectedBlocks, row.widthWithConnectedBlocks);
435
- // Add padding to the bottom row if block height is less than minimum
436
- const heightWithoutHat = yCursor - this.topRow.ascenderHeight;
437
- if (row === this.bottomRow &&
438
- heightWithoutHat < this.constants_.MIN_BLOCK_HEIGHT) {
439
- // But the hat height shouldn't be part of this.
440
- const diff = this.constants_.MIN_BLOCK_HEIGHT - heightWithoutHat;
441
- this.bottomRow.height += diff;
442
- yCursor += diff;
443
- }
444
- this.recordElemPositions_(row);
445
- }
446
- if (this.outputConnection && this.block_.nextConnection &&
447
- this.block_.nextConnection.isConnected()) {
448
- // Include width of connected block in value to stack width measurement.
449
- widestRowWithConnectedBlocks = Math.max(
450
- widestRowWithConnectedBlocks,
451
- this.block_.nextConnection.targetBlock().getHeightWidth().width -
452
- this.constants_.DARK_PATH_OFFSET);
479
+ // The dark (lowlight) adds to the size of the block in both x and y.
480
+ this.widthWithChildren = widestRowWithConnectedBlocks + this.startX +
481
+ this.constants_.DARK_PATH_OFFSET;
482
+ this.width += this.constants_.DARK_PATH_OFFSET;
483
+ this.height = yCursor + this.constants_.DARK_PATH_OFFSET;
484
+ this.startY = this.topRow.capline;
453
485
  }
454
-
455
- this.bottomRow.baseline = yCursor - this.bottomRow.descenderHeight;
456
-
457
- // The dark (lowlight) adds to the size of the block in both x and y.
458
- this.widthWithChildren = widestRowWithConnectedBlocks + this.startX +
459
- this.constants_.DARK_PATH_OFFSET;
460
- this.width += this.constants_.DARK_PATH_OFFSET;
461
- this.height = yCursor + this.constants_.DARK_PATH_OFFSET;
462
- this.startY = this.topRow.capline;
463
- };
486
+ }
464
487
 
465
488
  exports.RenderInfo = RenderInfo;