@@ -310,3 +310,99 @@ function performLayout(constraintSpace, box) {
310310 return new Fragment (fragmentDict);
311311}
312312```
313+
314+ ### Example layout algorithms
315+
316+ ``` js
317+ // 'multicol' does a simple multi-column layout.
318+ registerLayout (' multicol' , class {
319+ * layout (constraintSpace , children , styleMap , opt_breakToken ) {
320+ const inlineSize = resolveInlineSize (constraintSpace, styleMap);
321+
322+ // Try and decide the number of size of columns.
323+ const columnCountValue = styleMap .get (' column-count' );
324+ const columnInlineSizeValue = styleMap .get (' column-width' );
325+
326+ let columnCount = 1 ;
327+ let columnInlineSize = inlineSize;
328+
329+ if (columnCountValue) {
330+ columnCount = columnCountValue .value ;
331+ }
332+
333+ if (columnInlineSizeValue) {
334+ columnInlineSize = resolveSize (columnInlineSizeValue, inlineSize);
335+ }
336+
337+ if (constraintSpace .inlineScrollOffset &&
338+ columnInlineSize * columnCount > constraintSpace .inlineScrollOffset ) {
339+ // NOTE: under this condition, we need to start again to re-resolve lengths?
340+ constraintSpace .willInlineScroll ();
341+ return ; // Or just continue here?
342+ }
343+
344+ // Create a constraint space which is just the inlineSize of the column.
345+ const colConstraintSpace = new ConstraintSpace ({
346+ inlineSize: columnInlineSize
347+ });
348+
349+ // Perform layout on all the children, taking into account the children
350+ // which may fragment in the inline direction.
351+ const childFragments = [];
352+ let childBlockSize = 0 ;
353+ let layoutOpp;
354+ for (let child of children) {
355+ let breakToken;
356+ do {
357+ const fragment = yield child .doLayout (colConstraintSpace, breakToken);
358+ breakToken = fragment .breakToken ;
359+
360+ const gen = colConstraintSpace .layoutOpportunities ();
361+
362+ layoutOpp = gen .next ().value ;
363+ if (layoutOpp .inlineSize < fragment .inlineSize ()) {
364+ layoutOpp = gen .next ().value ;
365+ }
366+
367+ fragment .inlineStart = opp .inlineStart ;
368+ fragment .blockStart = opp .blockStart ;
369+ colConstraintSpace .addExclusion (fragment, ' inline-flow' );
370+
371+ childFragments .push (fragment);
372+ } while (breakToken);
373+ }
374+
375+ // FIXME: This might be wrong.
376+ const childBlockSize =
377+ colConstraintSpace .layoutOpportunities ().next ().value .blockStart ;
378+
379+ // Next, a clever person would nicely balance the columns, we are going
380+ // to do something really simple. :)
381+ const columnBlockSize = Math .ceil (childBlockSize / columnCount);
382+ const columnGap = resolveSize (styleMap .get (' column-gap' ), inlineSize);
383+ let size = 0 ;
384+ let columnNum = 0 ;
385+ let columnEndOffset = 0 ;
386+ for (let fragment of childFragments) {
387+ if (size && fragment .blockSize + size > columnBlockSize) {
388+ size = 0 ;
389+ columnNum++ ;
390+ columnEndOffset += size;
391+ }
392+
393+ fragment .inlineStart += columnNum * (columnGap + columnInlineSize);
394+ fragment .blockStart -= columnEndOffset;
395+ size = Math .max (size, fragment .blockStart + fragment .blockSize );
396+ }
397+
398+ const blockSize =
399+ resolveBlockSize (constraintSpace, styleMap, columnBlockSize);
400+
401+ return {
402+ inlineSize: inlineSize,
403+ blockSize: blockSize,
404+ fragments: childFragments,
405+ };
406+ }
407+ });
408+ ```
0 commit comments