2
0

layout.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2021 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.addHTML = addHTML;
  27. exports.checkDimensions = checkDimensions;
  28. exports.flushHTML = flushHTML;
  29. exports.getAvailableSpace = getAvailableSpace;
  30. var _xfa_object = require("./xfa_object.js");
  31. var _html_utils = require("./html_utils.js");
  32. function createLine(node, children) {
  33. return {
  34. name: "div",
  35. attributes: {
  36. class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"]
  37. },
  38. children
  39. };
  40. }
  41. function flushHTML(node) {
  42. if (!node[_xfa_object.$extra]) {
  43. return null;
  44. }
  45. const attributes = node[_xfa_object.$extra].attributes;
  46. const html = {
  47. name: "div",
  48. attributes,
  49. children: node[_xfa_object.$extra].children
  50. };
  51. if (node[_xfa_object.$extra].failingNode) {
  52. const htmlFromFailing = node[_xfa_object.$extra].failingNode[_xfa_object.$flushHTML]();
  53. if (htmlFromFailing) {
  54. if (node.layout.endsWith("-tb")) {
  55. html.children.push(createLine(node, [htmlFromFailing]));
  56. } else {
  57. html.children.push(htmlFromFailing);
  58. }
  59. }
  60. }
  61. if (html.children.length === 0) {
  62. return null;
  63. }
  64. return html;
  65. }
  66. function addHTML(node, html, bbox) {
  67. const extra = node[_xfa_object.$extra];
  68. const availableSpace = extra.availableSpace;
  69. const [x, y, w, h] = bbox;
  70. switch (node.layout) {
  71. case "position":
  72. {
  73. extra.width = Math.max(extra.width, x + w);
  74. extra.height = Math.max(extra.height, y + h);
  75. extra.children.push(html);
  76. break;
  77. }
  78. case "lr-tb":
  79. case "rl-tb":
  80. if (!extra.line || extra.attempt === 1) {
  81. extra.line = createLine(node, []);
  82. extra.children.push(extra.line);
  83. extra.numberInLine = 0;
  84. }
  85. extra.numberInLine += 1;
  86. extra.line.children.push(html);
  87. if (extra.attempt === 0) {
  88. extra.currentWidth += w;
  89. extra.height = Math.max(extra.height, extra.prevHeight + h);
  90. } else {
  91. extra.currentWidth = w;
  92. extra.prevHeight = extra.height;
  93. extra.height += h;
  94. extra.attempt = 0;
  95. }
  96. extra.width = Math.max(extra.width, extra.currentWidth);
  97. break;
  98. case "rl-row":
  99. case "row":
  100. {
  101. extra.children.push(html);
  102. extra.width += w;
  103. extra.height = Math.max(extra.height, h);
  104. const height = (0, _html_utils.measureToString)(extra.height);
  105. for (const child of extra.children) {
  106. child.attributes.style.height = height;
  107. }
  108. break;
  109. }
  110. case "table":
  111. {
  112. extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));
  113. extra.height += h;
  114. extra.children.push(html);
  115. break;
  116. }
  117. case "tb":
  118. {
  119. extra.width = availableSpace.width;
  120. extra.height += h;
  121. extra.children.push(html);
  122. break;
  123. }
  124. }
  125. }
  126. function getAvailableSpace(node) {
  127. const availableSpace = node[_xfa_object.$extra].availableSpace;
  128. const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0;
  129. const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0;
  130. switch (node.layout) {
  131. case "lr-tb":
  132. case "rl-tb":
  133. if (node[_xfa_object.$extra].attempt === 0) {
  134. return {
  135. width: availableSpace.width - marginH - node[_xfa_object.$extra].currentWidth,
  136. height: availableSpace.height - marginV - node[_xfa_object.$extra].prevHeight
  137. };
  138. }
  139. return {
  140. width: availableSpace.width - marginH,
  141. height: availableSpace.height - marginV - node[_xfa_object.$extra].height
  142. };
  143. case "rl-row":
  144. case "row":
  145. const width = node[_xfa_object.$extra].columnWidths.slice(node[_xfa_object.$extra].currentColumn).reduce((a, x) => a + x);
  146. return {
  147. width,
  148. height: availableSpace.height - marginH
  149. };
  150. case "table":
  151. case "tb":
  152. return {
  153. width: availableSpace.width - marginH,
  154. height: availableSpace.height - marginV - node[_xfa_object.$extra].height
  155. };
  156. case "position":
  157. default:
  158. return availableSpace;
  159. }
  160. }
  161. function getTransformedBBox(node) {
  162. let w = node.w === "" ? NaN : node.w;
  163. let h = node.h === "" ? NaN : node.h;
  164. let [centerX, centerY] = [0, 0];
  165. switch (node.anchorType || "") {
  166. case "bottomCenter":
  167. [centerX, centerY] = [w / 2, h];
  168. break;
  169. case "bottomLeft":
  170. [centerX, centerY] = [0, h];
  171. break;
  172. case "bottomRight":
  173. [centerX, centerY] = [w, h];
  174. break;
  175. case "middleCenter":
  176. [centerX, centerY] = [w / 2, h / 2];
  177. break;
  178. case "middleLeft":
  179. [centerX, centerY] = [0, h / 2];
  180. break;
  181. case "middleRight":
  182. [centerX, centerY] = [w, h / 2];
  183. break;
  184. case "topCenter":
  185. [centerX, centerY] = [w / 2, 0];
  186. break;
  187. case "topRight":
  188. [centerX, centerY] = [w, 0];
  189. break;
  190. }
  191. let x, y;
  192. switch (node.rotate || 0) {
  193. case 0:
  194. [x, y] = [-centerX, -centerY];
  195. break;
  196. case 90:
  197. [x, y] = [-centerY, centerX];
  198. [w, h] = [h, -w];
  199. break;
  200. case 180:
  201. [x, y] = [centerX, centerY];
  202. [w, h] = [-w, -h];
  203. break;
  204. case 270:
  205. [x, y] = [centerY, -centerX];
  206. [w, h] = [-h, w];
  207. break;
  208. }
  209. return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)];
  210. }
  211. function checkDimensions(node, space) {
  212. if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].firstUnsplittable === null) {
  213. return true;
  214. }
  215. if (node.w === 0 || node.h === 0) {
  216. return true;
  217. }
  218. const ERROR = 2;
  219. const parent = node[_xfa_object.$getSubformParent]();
  220. const attempt = parent[_xfa_object.$extra] && parent[_xfa_object.$extra].attempt || 0;
  221. const [, y, w, h] = getTransformedBBox(node);
  222. switch (parent.layout) {
  223. case "lr-tb":
  224. case "rl-tb":
  225. if (attempt === 0) {
  226. if (!node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) {
  227. if (node.h !== "" && Math.round(h - space.height) > ERROR) {
  228. return false;
  229. }
  230. if (node.w !== "") {
  231. if (Math.round(w - space.width) <= ERROR) {
  232. return true;
  233. }
  234. if (parent[_xfa_object.$extra].numberInLine === 0) {
  235. return space.height > ERROR;
  236. }
  237. return false;
  238. }
  239. return space.width > ERROR;
  240. }
  241. if (node.w !== "") {
  242. return Math.round(w - space.width) <= ERROR;
  243. }
  244. return space.width > ERROR;
  245. }
  246. if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) {
  247. return true;
  248. }
  249. if (node.h !== "" && Math.round(h - space.height) > ERROR) {
  250. return false;
  251. }
  252. if (node.w === "" || Math.round(w - space.width) <= ERROR) {
  253. return space.height > ERROR;
  254. }
  255. if (parent[_xfa_object.$isThereMoreWidth]()) {
  256. return false;
  257. }
  258. return space.height > ERROR;
  259. case "table":
  260. case "tb":
  261. if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) {
  262. return true;
  263. }
  264. if (node.h !== "" && !node[_xfa_object.$isSplittable]()) {
  265. return Math.round(h - space.height) <= ERROR;
  266. }
  267. if (node.w === "" || Math.round(w - space.width) <= ERROR) {
  268. return space.height > ERROR;
  269. }
  270. if (parent[_xfa_object.$isThereMoreWidth]()) {
  271. return false;
  272. }
  273. return space.height > ERROR;
  274. case "position":
  275. if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) {
  276. return true;
  277. }
  278. if (node.h === "" || Math.round(h + y - space.height) <= ERROR) {
  279. return true;
  280. }
  281. const area = node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].currentContentArea;
  282. return h + y > area.h;
  283. case "rl-row":
  284. case "row":
  285. if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) {
  286. return true;
  287. }
  288. if (node.h !== "") {
  289. return Math.round(h - space.height) <= ERROR;
  290. }
  291. return true;
  292. default:
  293. return true;
  294. }
  295. }