|
50 | 50 | * attribute and an <code>img</code> DOM element as input, and is expected to |
51 | 51 | * set the <code>src</code> attribute of the <code>img</code> to the absolute URI of the image. |
52 | 52 | * <pre>displayForcedOnlyMode</pre> sets the (boolean) |
53 | | - * value of the IMSC1 displayForcedOnlyMode parameter. |
| 53 | + * value of the IMSC1 displayForcedOnlyMode parameter. The function returns |
| 54 | + * an opaque object that should passed in <code>previousISDState</code> when this function |
| 55 | + * is called for the next ISD, otherwise <code>previousISDState</code> should be set to |
| 56 | + * <code>null</code>. |
54 | 57 | * |
55 | 58 | * @param {Object} isd ISD to be rendered |
56 | 59 | * @param {Object} element Element into which the ISD is rendered |
|
62 | 65 | * @param {?boolean} displayForcedOnlyMode Value of the IMSC1 displayForcedOnlyMode parameter, |
63 | 66 | * or false if null |
64 | 67 | * @param {?module:imscUtils.ErrorHandler} errorHandler Error callback |
| 68 | + * @param {Object} previousISDState State saved during processing of the previous ISD, or null if initial call |
| 69 | + * @param {?boolean} enableRollUp Enables roll-up animations (see CEA 708) |
| 70 | + * @return {Object} ISD state to be provided when this funtion is called for the next ISD |
65 | 71 | */ |
66 | 72 |
|
67 | | - imscHTML.render = function (isd, element, imgResolver, eheight, ewidth, displayForcedOnlyMode, errorHandler) { |
| 73 | + imscHTML.render = function ( isd, |
| 74 | + element, |
| 75 | + imgResolver, |
| 76 | + eheight, |
| 77 | + ewidth, |
| 78 | + displayForcedOnlyMode, |
| 79 | + errorHandler, |
| 80 | + previousISDState, |
| 81 | + enableRollUp |
| 82 | + ) { |
68 | 83 |
|
69 | 84 | /* maintain aspect ratio if specified */ |
70 | 85 |
|
|
107 | 122 | imgResolver: imgResolver, |
108 | 123 | displayForcedOnlyMode: displayForcedOnlyMode || false, |
109 | 124 | isd: isd, |
110 | | - errorHandler: errorHandler |
| 125 | + errorHandler: errorHandler, |
| 126 | + previousISDState: previousISDState, |
| 127 | + enableRollUp : enableRollUp || false, |
| 128 | + currentISDState: {} |
111 | 129 | }; |
112 | 130 |
|
113 | 131 | element.appendChild(rootcontainer); |
|
118 | 136 |
|
119 | 137 | } |
120 | 138 |
|
| 139 | + return context.currentISDState; |
| 140 | + |
121 | 141 | }; |
122 | 142 |
|
123 | 143 | function processElement(context, dom_parent, isd_element) { |
|
263 | 283 |
|
264 | 284 | } |
265 | 285 |
|
| 286 | + /* region processing */ |
| 287 | + |
| 288 | + if (isd_element.kind === "region") { |
| 289 | + |
| 290 | + /* build line list */ |
| 291 | + |
| 292 | + var linelist = []; |
| 293 | + |
| 294 | + constructLineList(proc_e, linelist); |
| 295 | + |
| 296 | + /* perform roll up if needed */ |
| 297 | + |
| 298 | + var wdir = isd_element.styleAttrs[imscStyles.byName.writingMode.qname]; |
| 299 | + |
| 300 | + if ((wdir === "lrtb" || wdir === "lr" || wdir === "rltb" || wdir === "rl") && |
| 301 | + context.enableRollUp && |
| 302 | + isd_element.contents.length > 0 && |
| 303 | + isd_element.styleAttrs[imscStyles.byName.displayAlign.qname] === 'after') { |
| 304 | + |
| 305 | + /* horrible hack, perhaps default region id should be underscore everywhere? */ |
| 306 | + |
| 307 | + var rid = isd_element.id === '' ? '_' : isd_element.id; |
| 308 | + |
| 309 | + var rb = new RegionPBuffer(rid, linelist); |
| 310 | + |
| 311 | + context.currentISDState[rb.id] = rb; |
| 312 | + |
| 313 | + if (context.previousISDState && |
| 314 | + rb.id in context.previousISDState && |
| 315 | + context.previousISDState[rb.id].plist.length > 0 && |
| 316 | + rb.plist.length > 1 && |
| 317 | + rb.plist[rb.plist.length - 2].text === |
| 318 | + context.previousISDState[rb.id].plist[context.previousISDState[rb.id].plist.length - 1].text) { |
| 319 | + |
| 320 | + var body_elem = e.firstElementChild; |
| 321 | + |
| 322 | + body_elem.style.bottom = "-" + rb.plist[rb.plist.length - 1].height + "px"; |
| 323 | + body_elem.style.transition = "transform 0.4s"; |
| 324 | + body_elem.style.position = "relative"; |
| 325 | + body_elem.style.transform = "translateY(-" + rb.plist[rb.plist.length - 1].height + "px)"; |
| 326 | + |
| 327 | + } |
| 328 | + |
| 329 | + } |
| 330 | + |
| 331 | + } |
| 332 | + } |
| 333 | + |
| 334 | + |
| 335 | + function RegionPBuffer(id, lineList) { |
| 336 | + |
| 337 | + this.id = id; |
| 338 | + |
| 339 | + this.plist = lineList; |
| 340 | + |
266 | 341 | } |
267 | 342 |
|
268 | 343 | function pruneEmptySpans(element) { |
|
320 | 395 |
|
321 | 396 | } |
322 | 397 |
|
| 398 | + |
| 399 | + function constructLineList(element, llist) { |
| 400 | + |
| 401 | + if (element.childElementCount === 0 && element.localName === 'span') { |
| 402 | + |
| 403 | + var r = element.getBoundingClientRect(); |
| 404 | + |
| 405 | + if (llist.length === 0 || |
| 406 | + (!isSameLine(r.top, r.height, llist[llist.length - 1].top, llist[llist.length - 1].height)) |
| 407 | + ) { |
| 408 | + |
| 409 | + llist.push({ |
| 410 | + top: r.top, |
| 411 | + height: r.height, |
| 412 | + text: element.textContent |
| 413 | + }); |
| 414 | + |
| 415 | + } else { |
| 416 | + |
| 417 | + if (r.top < llist[llist.length - 1].top) { |
| 418 | + llist[llist.length - 1].top = r.top; |
| 419 | + } |
| 420 | + |
| 421 | + if (r.height > llist[llist.length - 1].height) { |
| 422 | + llist[llist.length - 1].height = r.height; |
| 423 | + } |
| 424 | + |
| 425 | + llist[llist.length - 1].text += element.textContent; |
| 426 | + |
| 427 | + } |
| 428 | + |
| 429 | + } else { |
| 430 | + |
| 431 | + |
| 432 | + var child = element.firstChild; |
| 433 | + |
| 434 | + while (child) { |
| 435 | + |
| 436 | + if (child.nodeType === Node.ELEMENT_NODE) { |
| 437 | + |
| 438 | + constructLineList(child, llist); |
| 439 | + |
| 440 | + } |
| 441 | + |
| 442 | + child = child.nextSibling; |
| 443 | + } |
| 444 | + } |
| 445 | + |
| 446 | + } |
| 447 | + |
323 | 448 | function isSameLine(top1, height1, top2, height2) { |
324 | 449 |
|
325 | 450 | return (((top1 + height1) < (top2 + height2)) && (top1 > top2)) || (((top2 + height2) <= (top1 + height1)) && (top2 >= top1)); |
|
0 commit comments