nehan
Version:
Html layout engine for paged-media written in Typescript
133 lines • 5.18 kB
JavaScript
import { Config, LayoutOutline, FloatRegion, LogicalCursorPos, LogicalSize, FlowFormatContext, HoriLogicalNodeEvaluator, VertLogicalNodeEvaluator, LogicalCssEvaluator, LogicalTextJustifier, } from './public-api';
export class FlowRootFormatContext extends FlowFormatContext {
constructor(env, parent) {
super(env, parent);
this.env = env;
this.parent = parent;
this.floatNodes = [];
this.pageCount = 0;
this.anchors = {};
this.outline = new LayoutOutline();
}
get flowRoot() {
return this;
}
getSectionAt(pageIndex) {
return this.outline.getSectionAt(pageIndex);
}
get boxPos() {
return {
offsetPos: { start: 0, before: 0 },
clientPos: {
start: this.contextBoxEdge.borderBoxStartSize,
before: this.contextBoxEdge.borderBoxBeforeSize
}
};
}
openElement(element) {
this.outline.openElement(element, this.pageCount);
}
closeElement(element) {
this.outline.closeElement(element);
}
createOutline(evaluator) {
return this.outline.acceptEvaluator(evaluator);
}
createElement(tagName, layoutNames, logicalNode) {
const node = document.createElement(tagName);
const element = logicalNode.env.element;
const originalTagName = element.tagName;
const id = logicalNode.env.element.id;
const anchor = this.getAnchor(id);
if (anchor && !anchor.dom) {
anchor.dom = node;
}
switch (originalTagName) {
case "a":
const href = element.getAttribute("href");
if (href) {
node.setAttribute("href", href);
}
const name = element.getAttribute("name");
if (name) {
node.setAttribute("name", name);
}
break;
}
node.className = layoutNames.concat(originalTagName).map(layoutName => `nehan-${layoutName}`).concat(element.classList.values().map(klass => `nehan-e-${klass}`)).join(" ");
logicalNode.dom = node;
return node;
}
createLogicalNodeEvaluator() {
const cssEvaluator = new LogicalCssEvaluator(this.env.writingMode);
switch (this.env.writingMode.value) {
case "horizontal-tb":
return new HoriLogicalNodeEvaluator(this, cssEvaluator, LogicalTextJustifier.instance);
case "vertical-rl":
case "vertical-lr":
return new VertLogicalNodeEvaluator(this, cssEvaluator, LogicalTextJustifier.instance);
default:
throw new Error(`undefined writing mode: ${this.env.writingMode.value}`);
}
}
setAnchor(name, anchor) {
this.anchors[name] = anchor;
}
getAnchor(name) {
return this.anchors[name];
}
getHeaderSection(element) {
return this.outline.getHeaderSection(element);
}
clearFloat(clear) {
if (!this.floatRegion) {
throw new Error("float region is not defined");
}
if (clear.isStart()) {
return this.floatRegion.clearStart();
}
if (clear.isEnd()) {
return this.floatRegion.clearEnd();
}
if (clear.isBoth()) {
return this.floatRegion.clearBoth();
}
throw new Error("clear direction is not defined");
}
addFloat(block, float, contextMeasure, flowRootPos) {
if (float.isNone()) {
console.error("float direction is not set! ignored.");
return;
}
if (!this.floatRegion) {
const regionSize = new LogicalSize({ measure: this.maxMeasure, extent: this.maxExtent });
this.floatRegion = new FloatRegion(regionSize, flowRootPos.before);
}
try {
if (Config.debugLayout) {
console.log("addFloat(%o, %o, ctxM:%d, flowRootPos:%o)", block, float, contextMeasure, flowRootPos);
}
const floatSize = new LogicalSize({
measure: block.size.measure + block.env.edge.measure,
extent: block.size.extent + block.env.edge.extent
});
const rect = float.isStart() ?
this.floatRegion.pushStart(flowRootPos.before, floatSize, contextMeasure) :
this.floatRegion.pushEnd(flowRootPos.before, floatSize, contextMeasure);
const start = float.isStart() ? flowRootPos.start : rect.start + block.env.edge.start;
block.layoutPos = new LogicalCursorPos({
start,
before: rect.before
});
this.floatNodes.push(block);
if (Config.debugLayout) {
console.log("added float. rect:%o, pos:%o", rect, block.layoutPos);
console.log("spaceMeasure at %d = %d", block.layoutPos.before, this.floatRegion.getSpaceMeasureAt(block.layoutPos.before));
}
}
catch (err) {
console.error(err);
}
}
}
//# sourceMappingURL=flow-root-format-context.js.map