UNPKG

blossom

Version:

Modern, Cross-Platform Application Framework

263 lines (239 loc) 10.8 kB
// ========================================================================== // Project: Blossom - Modern, Cross-Platform Application Framework // Copyright: ©2012 Fohr Motion Picture Studios. All rights reserved. // License: Licensed under the GPLv3 license (see BLOSSOM-LICENSE). // ========================================================================== /*globals sc_assert FAST_LAYOUT_FUNCTION BENCHMARK_LAYOUT_FUNCTION Float32Array */ SC.layoutFunctions = {}; if (! FAST_LAYOUT_FUNCTION) { SC.GetLayoutFunction = function(hmode, vmode, hmax, vmax, layoutMode) { SC.Benchmark.start("SC.GetLayoutFunction"); sc_assert(hmode >= 0 && hmode < 16); sc_assert(vmode >= 0 && vmode < 16); sc_assert(typeof hmax === "boolean"); sc_assert(typeof vmax === "boolean"); sc_assert(layoutMode >= 0 && layoutMode < 9); var shouldBenchmark = BENCHMARK_LAYOUT_FUNCTION; var funcName = ['sc', hmode, vmode, hmax, vmax, layoutMode].join('_'), func = SC.layoutFunctions[funcName]; if (!func) { // There are 9,216 unique layout functions. func = SC.layoutFunctions[funcName] = function(layout, pwidth, pheight, anchorX, anchorY, position, bounds) { if (shouldBenchmark) { var benchKey = funcName; SC.Benchmark.start(benchKey); } var minLayoutWidth, xAdjustment = 0, minLayoutHeight, yAdjustment = 0, maxLayoutWidth, maxLayoutHeight, x, y, width, height; // Clamp pwidth and pheight to min/max layout values. This is a // requirement for the layout process below: pwidth and pheight are // assumed to lie within the correct range. minLayoutWidth = layout[4]/*minLayoutWidth*/; if (pwidth < minLayoutWidth) { xAdjustment = minLayoutWidth - pwidth; // a positive number pwidth = minLayoutWidth; } else if (hmax) { maxLayoutWidth = layout[5]/*maxLayoutWidth*/; if (pwidth > maxLayoutWidth) { xAdjustment = maxLayoutWidth - pwidth; // a negative number pwidth = maxLayoutWidth; } } minLayoutHeight = layout[6]/*minLayoutHeight*/; if (pheight < minLayoutHeight) { yAdjustment = minLayoutHeight - pheight; // a positive number pheight = minLayoutHeight; } else if (vmax) { maxLayoutHeight = layout[7]/*maxLayoutHeight*/; if (pheight > maxLayoutHeight) { yAdjustment = maxLayoutHeight - pheight; // a negative number pheight = maxLayoutHeight; } } // Calculate x and width using layout and pwidth. Duplicate the switch // statement, sorted by left value the first time (for x), right value // the second time (for width). This keeps duplicate code at a minimum. switch (hmode) { case 0: // left, width case 1: // left percentage, width case 4: // right, width case 5: // right percentage, width case 8: // centerX, width case 9: // centerX percentage, width width = layout[1]/*width*/; break; case 2: // left, width percentage case 3: // left percentage, width percentage case 6: // right, width percentage case 7: // right percentage, width percentage case 10: // centerX, width percentage case 11: // centerX percentage, width percentage width = pwidth * layout[1]/*width percentage*/; break; // Each of the following cases require both the first and second // value. case 12: // left, right width = pwidth - layout[0]/*left*/ - layout[1]/*right*/; break; case 13: // left percentage, right width = pwidth - (pwidth * layout[0]/*left percentage*/) - layout[1]/*right*/; break; case 14: // left, right percentage width = pwidth - layout[0]/*left*/ - (pwidth * layout[1]/*right percentage*/); break; case 15: // left percentage, right percentage width = pwidth - (pwidth * layout[0]/*left percentage*/) - (pwidth * layout[1]/*right percentage*/); break; } switch (hmode) { case 0: // left, width case 2: // left, width percentage case 12: // left, right case 14: // left, right percentage x = layout[0]/*left*/; break; case 1: // left percentage, width case 3: // left percentage, width percentage case 13: // left percentage, right case 15: // left percentage, right percentage x = pwidth * layout[0]/*left percentage*/; break; case 4: // right, width case 6: // right, width percentage x = pwidth - layout[0]/*right*/ - width; break; case 5: // right percentage, width case 7: // right percentage, width percentage x = pwidth - (pwidth * layout[0]/*right percentage*/) - width; break; case 8: // centerX, width case 10: // centerX, width percentage x = (pwidth/2) + layout[0]/*centerX*/ - width/2; break; case 9: // centerX percentage, width case 11: // centerX percentage, width percentage x = (pwidth/2) + (pwidth * layout[0]/*centerX percentage*/) - width/2; break; } // Calculate position.y, bounds.height using layout and pheight. // Duplicate the switch statement, sorted by left value the first time // (for position.y), right value the second time (for bounds.height). // This keeps duplicate code at a minimum. switch (vmode) { case 0: // top, height case 1: // top percentage, height case 4: // bottom, height case 5: // bottom prcentage, height case 8: // centerY, height case 9: // centerY percentage, height height = layout[3]/*height*/; break; case 2: // top, height percentage case 3: // top percentage, height percentage case 6: // bottom, height percentage case 7: // bottom percentage, height percentage case 10: // centerY, height percentage case 11: // centerY percentage, height percentage height = pheight * layout[3]/*height percentage*/; break; // Each of the following cases require both the first and second value. case 12: // top, bottom height = pheight - layout[2]/*top*/ - layout[3]/*bottom*/; break; case 13: // top percentage, bottom height = pheight - (pheight * layout[2]/*top percentage*/) - layout[3]/*bottom*/; break; case 14: // top, bottom percentage height = pheight - layout[2]/*top*/ - (pheight * layout[3]/*bottom percentage*/); break; case 15: // top percentage, bottom percentage height = pheight - (pheight * layout[2]/*top percentage*/) - (pheight * layout[3]/*bottom percentage*/); break; } switch (vmode) { case 0: // top, height case 2: // top, height percentage case 12: // top, bottom case 14: // top, bottom percentage y = layout[2]/*top*/; break; case 1: // top percentage, height case 3: // top percentage, height percentage case 13: // top percentage, bottom case 15: // top percentage, bottom percentage y = pheight * layout[2]/*top percentage*/; break; case 4: // bottom, height case 6: // bottom, height percentage y = pheight - layout[2]/*bottom*/ - height; break; case 5: // bottom percentage, height case 7: // bottom percentage, height percentage y = pheight - (pheight * layout[2]/*bottom percentage*/) - height; break; case 8: // centerY, height case 10: // centerY, height percentage y = (pheight/2) + layout[2]/*centerY*/ - height/2; break; case 9: // centerY percentage, height case 11: // centerY percentage, height percentage y = (pheight/2) + (pheight * layout[2]/*centerY percentage*/) - height/2; break; } // All adjustments only affect x and y (position.x and position.y). // Bounds are left unchanged. if (xAdjustment !== 0 || yAdjustment !== 0) { switch (layoutMode) { case 0: // align center case 1: // align top case 2: // align bottom x += xAdjustment/2; break; // case 3: // align left // case 5: // align top left // case 7: // align bottom left // // x is already correct // break; case 4: // align right case 6: // align top right case 8: // align bottom right x += xAdjustment; break; } switch (layoutMode) { case 0: // align center case 3: // align left case 4: // align right y += yAdjustment/2; break; // case 1: // align top // case 5: // align top left // case 6: // align top right // // y is already correct // break; case 2: // align bottom case 7: // align bottom left case 8: // align bottom right y += yAdjustment; break; } } // Update the position and bounds structs with the newly-computed // values, offset to take into account anchorX and anchorY. position.x = Math.floor(x + anchorX * width); position.y = Math.floor(y + anchorY * height); bounds.width = Math.ceil(width); bounds.height = Math.ceil(height); if (shouldBenchmark) { SC.Benchmark.end(benchKey); } }; } SC.Benchmark.end("SC.GetLayoutFunction"); return func; }; } // ! FAST_LAYOUT_FUNCTION