diff --git a/packages/core/src/vivliostyle/assets.ts b/packages/core/src/vivliostyle/assets.ts index 71d414ddd..e3e2d8f7d 100644 --- a/packages/core/src/vivliostyle/assets.ts +++ b/packages/core/src/vivliostyle/assets.ts @@ -285,7 +285,7 @@ border-image-outset = [NUM | LENGTH]{1,4}; border-image-repeat = [ stretch | repeat | round | space ]{1,2}; bottom = APLENGTH; caption-side = top | bottom; -clear = none | left | right | top | bottom | both | all | same; +clear = none | left | right | top | bottom | inline-start | inline-end | block-start | block-end | both | all | same; clip = rect(ALENGTH{4}) | rect(SPACE(ALENGTH{4})) | auto; color = COLOR; LIST_STYLE_TYPE = IDENT; @@ -510,7 +510,7 @@ crop-offset = auto | LENGTH; /* CSS Page Floats */ float-reference = inline | column | region | page; -float = block-start | block-end | inline-start | inline-end | snap-block | snap-inline | left | right | top | bottom | none | footnote; +float = none | footnote | [ block-start || block-end || inline-start || inline-end || snap-block || snap-inline || left || right || top || bottom ]; float-min-wrap-block = PPLENGTH; /* CSS Ruby */ diff --git a/packages/core/src/vivliostyle/css-validator.ts b/packages/core/src/vivliostyle/css-validator.ts index 170a74c40..75de8ccac 100644 --- a/packages/core/src/vivliostyle/css-validator.ts +++ b/packages/core/src/vivliostyle/css-validator.ts @@ -21,7 +21,7 @@ */ import * as Css from "./css"; import * as CssTokenizer from "./css-tokenizer"; -import * as Logging from "./logging"; +import * as Base from "./base"; import { ValidationTxt } from "./assets"; import { TokenType } from "./css-tokenizer"; @@ -2099,6 +2099,8 @@ export class ValidatorSet { if (CSS.supports(name, value.toString())) { // Browser supports this property receiver.simpleProperty(origName, value, important); + } else if (prefix && !Base.knownPrefixes.includes(`-${prefix}-`)) { + // Ignore properties with unknown prefix to avoid unnecessary warnings } else { receiver.unknownProperty(origName, value); } diff --git a/packages/core/src/vivliostyle/css.ts b/packages/core/src/vivliostyle/css.ts index c4cd4b0ae..22c10801b 100644 --- a/packages/core/src/vivliostyle/css.ts +++ b/packages/core/src/vivliostyle/css.ts @@ -679,6 +679,7 @@ export const ident: { [key: string]: Ident } = { same: getName("same"), scale: getName("scale"), snap_block: getName("snap-block"), + snap_inline: getName("snap-inline"), solid: getName("solid"), spread: getName("spread"), _static: getName("static"), diff --git a/packages/core/src/vivliostyle/display.ts b/packages/core/src/vivliostyle/display.ts index 6a0d2639a..bbb0b94b3 100644 --- a/packages/core/src/vivliostyle/display.ts +++ b/packages/core/src/vivliostyle/display.ts @@ -84,9 +84,9 @@ export function isRunning(position: Css.Val): boolean { export function getComputedDisplayValue( display: Css.Ident, position: Css.Ident, - float: Css.Ident, + float: Css.Val, isRoot: boolean, -): { display: Css.Ident; position: Css.Ident; float: Css.Ident } { +): { display: Css.Ident; position: Css.Ident; float: Css.Val } { if (display === Css.ident.none) { // no need to convert values when 'display' is 'none' } else if (isAbsolutelyPositioned(position)) { @@ -107,7 +107,7 @@ export function getComputedDisplayValue( export function isBlock( display: Css.Ident, position: Css.Ident, - float: Css.Ident, + float: Css.Val, isRoot: boolean, ): boolean { return ( @@ -149,7 +149,7 @@ export function isRubyInternalDisplay(display: Css.Ident | string): boolean { export function establishesBFC( display: Css.Ident, position: Css.Ident, - float: Css.Ident, + float: Css.Val, overflow: Css.Ident, writingMode?: Css.Ident, parentWritingMode?: Css.Ident, diff --git a/packages/core/src/vivliostyle/layout.ts b/packages/core/src/vivliostyle/layout.ts index 87b755b7f..ed399f768 100644 --- a/packages/core/src/vivliostyle/layout.ts +++ b/packages/core/src/vivliostyle/layout.ts @@ -2663,7 +2663,14 @@ export class Column extends VtreeImpl.Container implements Layout.Column { this, ); } - switch (clear) { + const clearLR = /^(top|bottom|(block|inline)-(start|end))$/.test(clear) + ? PageFloats.resolveInlineFloatDirection( + clear, + nodeContext.vertical, + nodeContext.direction, + ) + : clear; + switch (clearLR) { case "left": clearEdge = dir * Math.max(clearEdge * dir, this.leftFloatEdge * dir); break; diff --git a/packages/core/src/vivliostyle/page-floats.ts b/packages/core/src/vivliostyle/page-floats.ts index e367e68a7..8806f4462 100644 --- a/packages/core/src/vivliostyle/page-floats.ts +++ b/packages/core/src/vivliostyle/page-floats.ts @@ -805,14 +805,65 @@ export class PageFloatLayoutContext return CssLogicalUtil.toPhysical(side, writingMode, direction); } + private toLogicalFloatSides(floatSide: string): string[] { + const sides = floatSide.split(" "); + + // Convert to logical sides and remove duplicates + const logicalSides: string[] = []; + for (const side of sides) { + const logicalSide = this.toLogical(side); + if (!logicalSides.includes(logicalSide)) { + logicalSides.push(logicalSide); + } + } + + // Convert "block-start block-end" to "snap-block" and + // "inline-start inline-end" to "snap-inline". + // More precisely, when multiple "*block*" values are found + // convert the first one to "snap-block" and remove the rest, + // and when multiple "*inline*" values are found convert the + // first one to "snap-inline" and remove the rest. + const logicalFloatSides: string[] = []; + let foundSnapBlock = false; + let foundSnapInline = false; + for (let i = 0; i < logicalSides.length; i++) { + const side = logicalSides[i]; + if (side.includes("block")) { + if (!foundSnapBlock) { + // Convert to "snap-block" if another block side is found + if (logicalSides.slice(i + 1).some((s) => s.includes("block"))) { + logicalFloatSides.push("snap-block"); + foundSnapBlock = true; + } else { + logicalFloatSides.push(side); + } + } + } else if (side.includes("inline")) { + if (!foundSnapInline) { + // Convert to "snap-inline" if another inline side is found + if (logicalSides.slice(i + 1).some((s) => s.includes("inline"))) { + logicalFloatSides.push("snap-inline"); + foundSnapInline = true; + } else { + logicalFloatSides.push(side); + } + } + } + } + + return logicalFloatSides; + } + removeEndFloatFragments(floatSide: string) { - const logicalFloatSide = this.toLogical(floatSide); + const logicalFloatSide = this.toLogicalFloatSides(floatSide)[0]; if (logicalFloatSide === "block-end" || logicalFloatSide === "inline-end") { let i = 0; while (i < this.floatFragments.length) { const fragment = this.floatFragments[i]; - const logicalFloatSide2 = this.toLogical(fragment.floatSide); - if (logicalFloatSide2 === logicalFloatSide) { + const fragmentFloatSide = this.toLogicalFloatSides( + fragment.floatSide, + )[0]; + if (fragmentFloatSide === logicalFloatSide) { this.removePageFloatFragment(fragment); } else { i++; @@ -827,20 +878,25 @@ export class PageFloatLayoutContext this.getParent(floatReference).stashEndFloatFragments(float); return; } - const logicalFloatSide = this.toLogical(float.floatSide); + const logicalFloatSide = this.toLogicalFloatSides(float.floatSide)[0]; if ( logicalFloatSide === "block-end" || logicalFloatSide === "snap-block" || - logicalFloatSide === "inline-end" + logicalFloatSide === "inline-end" || + logicalFloatSide === "snap-inline" ) { let i = 0; while (i < this.floatFragments.length) { const fragment = this.floatFragments[i]; - const fragmentFloatSide = this.toLogical(fragment.floatSide); + const fragmentFloatSide = this.toLogicalFloatSides( + fragment.floatSide, + )[0]; if ( (fragmentFloatSide === logicalFloatSide || (logicalFloatSide === "snap-block" && - fragmentFloatSide === "block-end")) && + fragmentFloatSide === "block-end") || + (logicalFloatSide === "snap-inline" && + fragmentFloatSide === "inline-end")) && fragment.shouldBeStashedBefore(float) ) { this.stashedFloatFragments.push(fragment); @@ -999,7 +1055,7 @@ export class PageFloatLayoutContext if (condition && !condition(f, this)) { return l; } - const logicalFloatSide = this.toLogical(f.floatSide); + const logicalFloatSide = this.toLogicalFloatSides(f.floatSide)[0]; const area = f.area; const floatMinWrapBlock = f.continuations[0].float.floatMinWrapBlock; let top = l.top; @@ -1112,13 +1168,17 @@ export class PageFloatLayoutContext condition, ); } - let logicalFloatSide = this.toLogical(floatSide); - if (logicalFloatSide === "snap-block") { + const logicalFloatSides = this.toLogicalFloatSides(floatSide); + if (logicalFloatSides[0] === "snap-block") { if (!condition["block-start"] && !condition["block-end"]) { return null; } + } else if (logicalFloatSides[0] === "snap-inline") { + if (!condition["inline-start"] && !condition["inline-end"]) { + return null; + } } else { - if (!condition[logicalFloatSide]) { + if (!condition[logicalFloatSides[0]]) { return null; } } @@ -1194,9 +1254,10 @@ export class PageFloatLayoutContext ) : new GeometryUtil.Rect(inlineStart, blockStart, inlineEnd, blockEnd); if ( - logicalFloatSide === "block-start" || - logicalFloatSide === "snap-block" || - logicalFloatSide === "inline-start" + logicalFloatSides[0] === "block-start" || + logicalFloatSides[0] === "snap-block" || + logicalFloatSides[0] === "inline-start" || + logicalFloatSides[0] === "snap-inline" ) { if ( !limitBlockStartEndValueWithOpenRect( @@ -1208,9 +1269,10 @@ export class PageFloatLayoutContext } } if ( - logicalFloatSide === "block-end" || - logicalFloatSide === "snap-block" || - logicalFloatSide === "inline-end" + logicalFloatSides[0] === "block-end" || + logicalFloatSides[0] === "snap-block" || + logicalFloatSides[0] === "inline-end" || + logicalFloatSides[0] === "snap-inline" ) { if ( !limitBlockStartEndValueWithOpenRect( @@ -1232,10 +1294,10 @@ export class PageFloatLayoutContext blockSize = area.computedBlockSize; outerBlockSize = blockSize + area.getInsetBefore() + area.getInsetAfter(); const availableBlockSize = (blockEnd - blockStart) * area.getBoxDir(); - if (logicalFloatSide === "snap-block") { + if (logicalFloatSides[0] === "snap-block") { if (anchorEdge === null) { // Deferred from previous container - logicalFloatSide = "block-start"; + logicalFloatSides[0] = "block-start"; } else { const containerRect = this.container.getPaddingRect(); const fromStart = @@ -1248,14 +1310,28 @@ export class PageFloatLayoutContext anchorEdge - outerBlockSize); if (fromStart <= fromEnd) { - logicalFloatSide = "block-start"; + logicalFloatSides[0] = "block-start"; } else { - logicalFloatSide = "block-end"; + logicalFloatSides[0] = "block-end"; } } - if (!condition[logicalFloatSide]) { + if (!condition[logicalFloatSides[0]]) { if (condition["block-end"]) { - logicalFloatSide = "block-end"; + logicalFloatSides[0] = "block-end"; + } else { + return null; + } + } + } else if (logicalFloatSides[0] === "snap-inline") { + if (anchorEdge === null) { + // Deferred from previous container + logicalFloatSides[0] = "inline-start"; + } else { + // FIXME: snap-inline should be resolved based on the anchor's inline position + if (condition["inline-start"]) { + logicalFloatSides[0] = "inline-start"; + } else if (condition["inline-end"]) { + logicalFloatSides[0] = "inline-end"; } else { return null; } @@ -1265,9 +1341,12 @@ export class PageFloatLayoutContext return null; } if ( - logicalFloatSide === "inline-start" || - logicalFloatSide === "inline-end" + logicalFloatSides[0] === "inline-start" || + logicalFloatSides[0] === "inline-end" || + logicalFloatSides[1] ) { + // If the page float is "inline-start" or "inline-end" or has two sides + // (e.g. "block-start inline-end"), the inline size is determined by the content size. inlineSize = Sizing.getSize(area.clientLayout, area.element, [ Sizing.Size.FIT_CONTENT_INLINE_SIZE, ])[Sizing.Size.FIT_CONTENT_INLINE_SIZE]; @@ -1287,28 +1366,45 @@ export class PageFloatLayoutContext blockEnd -= blockOffset; inlineStart -= inlineOffset; inlineEnd -= inlineOffset; - switch (logicalFloatSide) { - case "inline-start": - case "block-start": - case "snap-block": - area.setInlinePosition(inlineStart, inlineSize); - area.setBlockPosition(blockStart, blockSize); - break; - case "inline-end": - case "block-end": - area.setInlinePosition( - inlineEnd - outerInlineSize * area.getInlineDir(), - inlineSize, - ); - area.setBlockPosition( - blockEnd - outerBlockSize * area.getBoxDir(), - blockSize, - ); - break; - default: - throw new Error(`unknown float direction: ${floatSide}`); + + if ( + logicalFloatSides.some( + (s) => s === "inline-start" || s === "snap-inline", + ) || + (logicalFloatSides.length === 1 && + (logicalFloatSides[0] === "block-start" || + logicalFloatSides[0] === "snap-block")) + ) { + area.setInlinePosition(inlineStart, inlineSize); + } else if ( + logicalFloatSides.some((s) => s === "inline-end") || + (logicalFloatSides.length === 1 && logicalFloatSides[0] === "block-end") + ) { + area.setInlinePosition( + inlineEnd - outerInlineSize * area.getInlineDir(), + inlineSize, + ); + } + if ( + logicalFloatSides.some( + (s) => s === "block-start" || s === "snap-block", + ) || + (logicalFloatSides.length === 1 && + (logicalFloatSides[0] === "inline-start" || + logicalFloatSides[0] === "snap-inline")) + ) { + area.setBlockPosition(blockStart, blockSize); + } else if ( + logicalFloatSides.some((s) => s === "block-end") || + (logicalFloatSides.length === 1 && logicalFloatSides[0] === "inline-end") + ) { + area.setBlockPosition( + blockEnd - outerBlockSize * area.getBoxDir(), + blockSize, + ); } - return logicalFloatSide; + + return logicalFloatSides.join(" "); } getFloatFragmentExclusions(): GeometryUtil.Shape[] { @@ -1428,7 +1524,7 @@ export class PageFloatLayoutContext if (!clearSide) { return result; } - const logicalFloatSide = this.toLogical(floatSide); + const logicalFloatSide = this.toLogicalFloatSides(floatSide)[0]; const logicalClearSide = this.toLogical(clearSide); let logicalSides: string[]; if (logicalClearSide === "all") { diff --git a/packages/core/src/vivliostyle/plugin.ts b/packages/core/src/vivliostyle/plugin.ts index 926a84c6c..de1d24726 100644 --- a/packages/core/src/vivliostyle/plugin.ts +++ b/packages/core/src/vivliostyle/plugin.ts @@ -167,7 +167,7 @@ export type ResolveFormattingContextHook = ( p2: boolean, p3: Css.Ident, p4: Css.Ident, - p5: Css.Ident, + p5: Css.Val, p6: boolean, ) => Vtree.FormattingContext; diff --git a/packages/core/src/vivliostyle/sizing.ts b/packages/core/src/vivliostyle/sizing.ts index d062e68cf..cd1c7d9b5 100644 --- a/packages/core/src/vivliostyle/sizing.ts +++ b/packages/core/src/vivliostyle/sizing.ts @@ -60,6 +60,10 @@ export function getSize( height: (element as any).style.height as string, maxHeight: (element as any).style.maxHeight as string, minHeight: (element as any).style.minHeight as string, + top: (element as any).style.top as string, + right: (element as any).style.right as string, + bottom: (element as any).style.bottom as string, + left: (element as any).style.left as string, }; const doc = element.ownerDocument; const parent = element.parentNode; @@ -92,9 +96,27 @@ export function getSize( const blockSizeName = isVertical ? "width" : "height"; function getFillAvailableInline(): string { + if (original.position === "absolute" || original.position === "fixed") { + // For absolutely positioned elements, use the element's original size + // and position to calculate the fill-available inline size. + // This is needed to get correct available inline size for page floats. + Base.setCSSProperty(container, "width", original.width); + Base.setCSSProperty(container, "height", original.height); + Base.setCSSProperty(container, "top", original.top); + Base.setCSSProperty(container, "right", original.right); + Base.setCSSProperty(container, "bottom", original.bottom); + Base.setCSSProperty(container, "left", original.left); + } Base.setCSSProperty(element, "display", "block"); Base.setCSSProperty(element, "position", "static"); - return getComputedValue(inlineSizeName); + const r = getComputedValue(inlineSizeName); + Base.setCSSProperty(container, "width", ""); + Base.setCSSProperty(container, "height", ""); + Base.setCSSProperty(container, "top", ""); + Base.setCSSProperty(container, "right", ""); + Base.setCSSProperty(container, "bottom", ""); + Base.setCSSProperty(container, "left", ""); + return r; } // Inline size of an inline-block element is the fit-content diff --git a/packages/core/src/vivliostyle/table.ts b/packages/core/src/vivliostyle/table.ts index 9b395e26e..4af1bbf2e 100644 --- a/packages/core/src/vivliostyle/table.ts +++ b/packages/core/src/vivliostyle/table.ts @@ -2214,7 +2214,7 @@ function resolveFormattingContextHook( firstTime: boolean, display: Css.Ident, position: Css.Ident, - floatSide: Css.Ident, + floatSide: Css.Val, isRoot: boolean, ): TableFormattingContext | null { if (!firstTime) { diff --git a/packages/core/src/vivliostyle/vgen.ts b/packages/core/src/vivliostyle/vgen.ts index 5d9653912..b1dddf711 100644 --- a/packages/core/src/vivliostyle/vgen.ts +++ b/packages/core/src/vivliostyle/vgen.ts @@ -517,7 +517,7 @@ export class ViewFactory // Compute values of display, position and float const position = computedStyle["position"] as Css.Ident; - const float = computedStyle["float"] as Css.Ident; + const float = computedStyle["float"]; const display = (computedStyle["display"] as Css.Ident) || ((this.sourceNode as Element).namespaceURI === Base.NS.XHTML @@ -724,7 +724,7 @@ export class ViewFactory firstTime: boolean, display: Css.Ident, position: Css.Ident, - float: Css.Ident, + float: Css.Val, isRoot: boolean, ) { const hooks: Plugin.ResolveFormattingContextHook[] = Plugin.getHooksForName( @@ -872,7 +872,7 @@ export class ViewFactory ).then((shadowParam) => { this.nodeContext.nodeShadow = shadowParam; const position = computedStyle["position"] as Css.Ident; - let floatSide = computedStyle["float"] as Css.Ident; + let floatSide = computedStyle["float"]; let clearSide = computedStyle["clear"] as Css.Ident; const writingMode = this.nodeContext.vertical ? Css.ident.vertical_rl @@ -906,6 +906,7 @@ export class ViewFactory clearSide = null; } let floating = + floatSide instanceof Css.SpaceList || floatSide === Css.ident.left || floatSide === Css.ident.right || floatSide === Css.ident.top || @@ -915,6 +916,7 @@ export class ViewFactory floatSide === Css.ident.block_start || floatSide === Css.ident.block_end || floatSide === Css.ident.snap_block || + floatSide === Css.ident.snap_inline || floatSide === Css.ident.footnote; if (floatSide) { // Don't want to set it in view DOM CSS. @@ -942,6 +944,10 @@ export class ViewFactory clearSide === Css.ident.right || clearSide === Css.ident.top || clearSide === Css.ident.bottom || + clearSide === Css.ident.inline_start || + clearSide === Css.ident.inline_end || + clearSide === Css.ident.block_start || + clearSide === Css.ident.block_end || clearSide === Css.ident.both || clearSide === Css.ident.all || clearSide === Css.ident.same diff --git a/packages/core/test/files/file-list.js b/packages/core/test/files/file-list.js index 62e793a4e..ca7a71c62 100644 --- a/packages/core/test/files/file-list.js +++ b/packages/core/test/files/file-list.js @@ -402,10 +402,18 @@ module.exports = [ file: "page_floats/page_page_floats.html", title: "'Page' page floats", }, + { + file: "page_floats/page_page_floats_2.html", + title: "'Page' page floats (2 values)", + }, { file: "page_floats/page_page_floats_vertical.html", title: "'Page' page floats (vertical writing-mode)", }, + { + file: "page_floats/page_page_floats_vertical_2.html", + title: "'Page' page floats (vertical writing-mode, 2 values)", + }, { file: "page_floats/region_page_floats.html", title: "'Region' page floats", @@ -418,10 +426,18 @@ module.exports = [ file: "page_floats/column_page_floats.html", title: "'Column' page floats", }, + { + file: "page_floats/column_page_floats_2.html", + title: "'Column' page floats (2 values)", + }, { file: "page_floats/column_page_floats_vertical.html", title: "'Column' page floats (vertical writing-mode)", }, + { + file: "page_floats/column_page_floats_vertical_2.html", + title: "'Column' page floats (vertical writing-mode, 2 values)", + }, { file: "page_floats/region_page_floats_with_exclusions.html", title: "'Region' page floats with exclusions", @@ -454,10 +470,18 @@ module.exports = [ file: "page_floats/inline_page_floats.html", title: "Inline page floats", }, + { + file: "page_floats/inline_page_floats_2.html", + title: "Inline page floats (2 values)", + }, { file: "page_floats/inline_page_floats_vertical.html", title: "Inline page floats (vertical writing-mode)", }, + { + file: "page_floats/inline_page_floats_vertical_2.html", + title: "Inline page floats (vertical writing-mode, 2 values)", + }, { file: "page_floats/forced_break_and_page_floats.html", title: "Forced break and page floats", @@ -499,6 +523,10 @@ module.exports = [ title: "column-span on page floats", }, { file: "page_floats/float_snap-block.html", title: "float: snap-block" }, + { + file: "page_floats/float_snap-block_2.html", + title: "float: snap-block (2 values)", + }, { file: "page_floats/clear_page_floats.html", title: "Clear page floats", diff --git a/packages/core/test/files/page_floats/column_page_floats_2.html b/packages/core/test/files/page_floats/column_page_floats_2.html new file mode 100644 index 000000000..30839566c --- /dev/null +++ b/packages/core/test/files/page_floats/column_page_floats_2.html @@ -0,0 +1,254 @@ + + +
+ ++ (1) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (2) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (3) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (4) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (5) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (6) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (7) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (8) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (9) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (10) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (11) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (12) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (13) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (14) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (1) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (2) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (3) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (4) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (5) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (6) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (7) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (8) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (9) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (10) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (11) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (12) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (13) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (14) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
+Text on page 1, column 1
+Text on page 1, column 1
+Text on page 1, column 1
+Text on page 1, column 2
+Text on page 1, column 2
+Text on page 1, column 2
+Text on page 2, column 1
+Text on page 2, column 1
+Text on page 2, column 1
+Text on page 2, column 2
+Text on page 2, column 2
+Text on page 2, column 2
+Text on page 3, column 1
+Text on page 3, column 1
+Text on page 3, column 1
+Text on page 3, column 2
+Text on page 3, column 2
+Text on page 3, column 2
+Text on page 4, column 1
+Text on page 4, column 1
+Text on page 5, column 1
+Text on page 5, column 1
+Text on page 6, column 1
+Text on page 6, column 1
+Text on page 6, column 1
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 6, column 2
+Text on page 7, column 1
+Text on page 7, column 1
+Text on page 7, column 1
+Text on page 7, column 1
+Text on page 7, column 1
+Text on page 7, column 1
+Text on page 7, column 1
++ (1) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (2) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (3) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (4) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (5) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (6) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (7) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (8) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (9) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (10) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (11) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (12) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (13) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (14) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (1) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (2) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (3) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (4) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (5) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (6) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (7) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (8) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (9) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (10) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (11) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. +
++ (12) Background of p elements is lightgray. This is normal text inside two + columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (13) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
++ (14) Background of p elements is light-gray. This is normal text inside + two columns. This is normal text inside two columns. This is normal text + inside two columns. This is normal text inside two columns. This is normal + text inside two columns. This is normal text inside two columns. +
+