2014-10-29 08:01:22 -07:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
|
|
|
|
2014-09-26 16:22:44 -07:00
|
|
|
var layoutTestUtils = require('./Layout-test-utils.js');
|
2015-02-07 00:01:35 -05:00
|
|
|
var computeLayout = require('./Layout.js').computeLayout;
|
2014-09-26 16:22:44 -07:00
|
|
|
var fs = require('fs');
|
2014-09-18 15:15:21 -07:00
|
|
|
var JavaTranspiler = require('./JavaTranspiler.js');
|
2014-09-26 16:22:44 -07:00
|
|
|
|
2014-04-18 17:15:03 -07:00
|
|
|
var currentTest = '';
|
|
|
|
var allTests = [];
|
2014-04-19 22:08:10 -07:00
|
|
|
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
2014-04-22 14:59:59 -07:00
|
|
|
var reduceTest = layoutTestUtils.reduceTest;
|
2014-09-26 16:22:44 -07:00
|
|
|
global.layoutTestUtils = {
|
2014-04-18 17:15:03 -07:00
|
|
|
testLayout: function(node, expectedLayout) {
|
|
|
|
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
|
|
|
},
|
|
|
|
testRandomLayout: function(node, i) {
|
2014-04-19 22:08:10 -07:00
|
|
|
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
2014-04-22 14:59:59 -07:00
|
|
|
},
|
2014-09-26 16:22:44 -07:00
|
|
|
computeLayout: layoutTestUtils.computeLayout,
|
2014-04-28 12:34:04 -07:00
|
|
|
reduceTest: reduceTest,
|
2014-09-26 16:22:44 -07:00
|
|
|
text: layoutTestUtils.text,
|
2014-09-25 16:05:01 -07:00
|
|
|
texts: layoutTestUtils.texts,
|
2014-09-26 16:22:44 -07:00
|
|
|
textSizes: layoutTestUtils.textSizes
|
2014-04-18 17:15:03 -07:00
|
|
|
};
|
2014-09-26 16:22:44 -07:00
|
|
|
|
2015-02-07 00:01:35 -05:00
|
|
|
global.describe = function(name, cb) {
|
2015-02-17 21:30:41 -05:00
|
|
|
if (name === 'Layout') {
|
2015-02-07 00:01:35 -05:00
|
|
|
cb();
|
|
|
|
}
|
|
|
|
};
|
2014-09-26 16:22:44 -07:00
|
|
|
global.it = function(name, cb) { currentTest = name; cb(); };
|
2014-09-26 17:52:27 -07:00
|
|
|
global.xit = function() { /* ignore skipped tests */ };
|
2014-09-26 16:22:44 -07:00
|
|
|
|
|
|
|
require('./__tests__/Layout-test.js');
|
|
|
|
|
2014-04-18 17:15:03 -07:00
|
|
|
|
|
|
|
function printLayout(test) {
|
|
|
|
var level = 1;
|
|
|
|
var res = [];
|
|
|
|
|
2015-02-17 21:12:29 -05:00
|
|
|
function indent(level) {
|
|
|
|
var result = '';
|
|
|
|
for (var i = 0; i < level; ++i) {
|
|
|
|
result += ' ';
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-04-18 17:15:03 -07:00
|
|
|
function add(str) {
|
2014-09-26 16:22:44 -07:00
|
|
|
if (str.length > 0) {
|
|
|
|
str = indent(level) + str;
|
|
|
|
}
|
|
|
|
res.push(str);
|
2014-04-18 17:15:03 -07:00
|
|
|
}
|
|
|
|
|
2014-05-16 18:04:24 -07:00
|
|
|
function isEmpty(obj) {
|
2015-02-17 21:12:29 -05:00
|
|
|
return !Object.keys(obj).length;
|
2014-04-18 17:15:03 -07:00
|
|
|
}
|
2014-04-19 12:11:45 -07:00
|
|
|
|
2014-05-16 18:04:24 -07:00
|
|
|
add('{');
|
|
|
|
level++;
|
|
|
|
|
|
|
|
// Output the style node
|
2014-09-11 09:23:30 -07:00
|
|
|
add('css_node_t *root_node = new_test_css_node();');
|
2014-05-16 18:04:24 -07:00
|
|
|
add('{');
|
|
|
|
level++;
|
|
|
|
if (!isEmpty(test.node.style) || test.node.children && test.node.children.length) {
|
|
|
|
add('css_node_t *node_0 = root_node;');
|
2014-04-19 12:11:45 -07:00
|
|
|
}
|
2015-02-17 21:12:29 -05:00
|
|
|
function recStyle(node) {
|
2014-04-19 12:11:45 -07:00
|
|
|
|
2014-05-16 18:04:24 -07:00
|
|
|
function addStyle(str) {
|
|
|
|
add('node_' + (level - 3) + '->style.' + str);
|
|
|
|
}
|
|
|
|
|
2015-02-17 21:12:29 -05:00
|
|
|
function addEnum(node, jsKey, cKey, dict) {
|
|
|
|
if (jsKey in node.style) {
|
|
|
|
addStyle(cKey + ' = ' + dict[node.style[jsKey]] + ';');
|
2014-04-22 14:59:59 -07:00
|
|
|
}
|
2014-04-19 12:11:45 -07:00
|
|
|
}
|
|
|
|
|
2015-03-22 14:36:16 +08:00
|
|
|
function addFloat(node, jsKey, cKey) {
|
2015-02-17 21:12:29 -05:00
|
|
|
if (jsKey in node.style) {
|
2015-03-22 14:36:16 +08:00
|
|
|
addStyle(cKey + ' = ' + node.style[jsKey] + ';');
|
2014-05-16 18:04:24 -07:00
|
|
|
}
|
|
|
|
}
|
2014-04-19 12:11:45 -07:00
|
|
|
|
2015-03-22 14:36:16 +08:00
|
|
|
function addSpacing(node, spacing, suffix) {
|
|
|
|
addFloat(node, spacing + suffix, spacing + '[CSS_LEFT]');
|
|
|
|
addFloat(node, spacing + suffix, spacing + '[CSS_TOP]');
|
|
|
|
addFloat(node, spacing + suffix, spacing + '[CSS_RIGHT]');
|
|
|
|
addFloat(node, spacing + suffix, spacing + '[CSS_BOTTOM]');
|
2014-04-19 12:11:45 -07:00
|
|
|
|
2015-03-22 14:36:16 +08:00
|
|
|
addFloat(node, spacing + 'Left' + suffix, spacing + '[CSS_LEFT]');
|
|
|
|
addFloat(node, spacing + 'Top' + suffix, spacing + '[CSS_TOP]');
|
|
|
|
addFloat(node, spacing + 'Right' + suffix, spacing + '[CSS_RIGHT]');
|
|
|
|
addFloat(node, spacing + 'Bottom' + suffix, spacing + '[CSS_BOTTOM]');
|
2014-04-28 12:34:04 -07:00
|
|
|
}
|
|
|
|
|
2014-05-16 18:04:24 -07:00
|
|
|
function addMeasure(node) {
|
|
|
|
if ('measure' in node.style) {
|
2014-06-11 21:00:57 -07:00
|
|
|
add('node_' + (level - 3) + '->measure = measure;');
|
|
|
|
add('node_' + (level - 3) + '->context = "' + node.style.measure.toString() + '";');
|
2014-05-16 18:04:24 -07:00
|
|
|
}
|
|
|
|
}
|
2014-04-19 14:26:19 -07:00
|
|
|
|
2014-04-19 12:15:01 -07:00
|
|
|
addEnum(node, 'flexDirection', 'flex_direction', {
|
|
|
|
'row': 'CSS_FLEX_DIRECTION_ROW',
|
|
|
|
'column': 'CSS_FLEX_DIRECTION_COLUMN'
|
|
|
|
});
|
|
|
|
addEnum(node, 'justifyContent', 'justify_content', {
|
|
|
|
'flex-start': 'CSS_JUSTIFY_FLEX_START',
|
|
|
|
'center': 'CSS_JUSTIFY_CENTER',
|
|
|
|
'flex-end': 'CSS_JUSTIFY_FLEX_END',
|
2014-04-19 15:21:57 -07:00
|
|
|
'space-between': 'CSS_JUSTIFY_SPACE_BETWEEN',
|
|
|
|
'space-around': 'CSS_JUSTIFY_SPACE_AROUND'
|
2014-04-19 12:15:01 -07:00
|
|
|
});
|
|
|
|
addEnum(node, 'alignItems', 'align_items', {
|
|
|
|
'flex-start': 'CSS_ALIGN_FLEX_START',
|
|
|
|
'center': 'CSS_ALIGN_CENTER',
|
|
|
|
'flex-end': 'CSS_ALIGN_FLEX_END',
|
|
|
|
'stretch': 'CSS_ALIGN_STRETCH'
|
|
|
|
});
|
|
|
|
addEnum(node, 'alignSelf', 'align_self', {
|
|
|
|
'flex-start': 'CSS_ALIGN_FLEX_START',
|
|
|
|
'center': 'CSS_ALIGN_CENTER',
|
|
|
|
'flex-end': 'CSS_ALIGN_FLEX_END',
|
|
|
|
'stretch': 'CSS_ALIGN_STRETCH'
|
|
|
|
});
|
2014-04-22 13:18:05 -07:00
|
|
|
addEnum(node, 'position', 'position_type', {
|
|
|
|
'relative': 'CSS_POSITION_RELATIVE',
|
|
|
|
'absolute': 'CSS_POSITION_ABSOLUTE'
|
|
|
|
});
|
2014-12-12 12:03:31 +00:00
|
|
|
addEnum(node, 'flexWrap', 'flex_wrap', {
|
|
|
|
'nowrap': 'CSS_NOWRAP',
|
|
|
|
'wrap': 'CSS_WRAP'
|
|
|
|
});
|
2015-03-22 14:36:16 +08:00
|
|
|
addFloat(node, 'flex', 'flex');
|
|
|
|
addFloat(node, 'width', 'dimensions[CSS_WIDTH]');
|
|
|
|
addFloat(node, 'height', 'dimensions[CSS_HEIGHT]');
|
|
|
|
addSpacing(node, 'margin', '');
|
|
|
|
addSpacing(node, 'padding', '');
|
|
|
|
addSpacing(node, 'border', 'Width');
|
|
|
|
addFloat(node, 'left', 'position[CSS_LEFT]');
|
|
|
|
addFloat(node, 'top', 'position[CSS_TOP]');
|
|
|
|
addFloat(node, 'right', 'position[CSS_RIGHT]');
|
|
|
|
addFloat(node, 'bottom', 'position[CSS_BOTTOM]');
|
2014-04-28 12:34:04 -07:00
|
|
|
addMeasure(node);
|
2014-04-19 12:11:45 -07:00
|
|
|
|
2014-04-19 12:15:01 -07:00
|
|
|
if (node.children) {
|
2015-02-17 21:12:29 -05:00
|
|
|
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
2014-04-18 17:15:03 -07:00
|
|
|
add('{');
|
|
|
|
level++;
|
2014-05-16 18:04:24 -07:00
|
|
|
add('css_node_t *node_' + (level - 3) + ';');
|
2014-04-18 17:15:03 -07:00
|
|
|
|
|
|
|
for (var i = 0; i < node.children.length; ++i) {
|
2014-09-11 09:23:30 -07:00
|
|
|
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
2015-02-17 21:12:29 -05:00
|
|
|
recStyle(node.children[i]);
|
2014-04-18 17:15:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
level--;
|
|
|
|
add('}');
|
|
|
|
}
|
|
|
|
}
|
2015-02-17 21:12:29 -05:00
|
|
|
recStyle(test.node);
|
2014-04-19 14:26:19 -07:00
|
|
|
level--;
|
|
|
|
add('}');
|
|
|
|
add('');
|
2014-04-18 17:15:03 -07:00
|
|
|
|
2014-04-19 14:35:54 -07:00
|
|
|
// Output the expected layout node
|
2014-09-11 09:23:30 -07:00
|
|
|
add('css_node_t *root_layout = new_test_css_node();');
|
2014-04-18 17:15:03 -07:00
|
|
|
add('{');
|
|
|
|
level++;
|
2014-05-16 18:04:24 -07:00
|
|
|
add('css_node_t *node_0 = root_layout;');
|
2014-04-19 14:26:19 -07:00
|
|
|
|
2015-02-17 21:12:29 -05:00
|
|
|
function recLayout(node) {
|
2014-05-16 18:04:24 -07:00
|
|
|
function addLayout(str) {
|
|
|
|
add('node_' + (level - 3) + '->layout.' + str);
|
|
|
|
}
|
|
|
|
|
|
|
|
addLayout('position[CSS_TOP] = ' + node.top + ';');
|
|
|
|
addLayout('position[CSS_LEFT] = ' + node.left + ';');
|
|
|
|
addLayout('dimensions[CSS_WIDTH] = ' + node.width + ';');
|
|
|
|
addLayout('dimensions[CSS_HEIGHT] = ' + node.height + ';');
|
2014-04-19 14:26:19 -07:00
|
|
|
|
|
|
|
if (node.children) {
|
2015-02-17 21:12:29 -05:00
|
|
|
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
2014-04-19 14:26:19 -07:00
|
|
|
add('{');
|
|
|
|
level++;
|
2014-05-16 18:04:24 -07:00
|
|
|
add('css_node_t *node_' + (level - 3) + ';');
|
2014-04-19 14:26:19 -07:00
|
|
|
|
|
|
|
for (var i = 0; i < node.children.length; ++i) {
|
2014-09-11 09:23:30 -07:00
|
|
|
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
2015-02-17 21:12:29 -05:00
|
|
|
recLayout(node.children[i]);
|
2014-04-19 14:26:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
level--;
|
|
|
|
add('}');
|
|
|
|
}
|
|
|
|
}
|
2015-02-17 21:12:29 -05:00
|
|
|
recLayout(test.expectedLayout);
|
2014-04-19 14:26:19 -07:00
|
|
|
level--;
|
|
|
|
add('}');
|
2014-04-19 14:35:54 -07:00
|
|
|
add('');
|
2014-04-19 14:26:19 -07:00
|
|
|
|
2014-04-19 14:35:54 -07:00
|
|
|
// Do the test
|
|
|
|
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
2014-04-18 17:15:03 -07:00
|
|
|
level--;
|
|
|
|
add('}');
|
|
|
|
return res.join('\n');
|
|
|
|
}
|
2014-09-26 16:22:44 -07:00
|
|
|
|
|
|
|
function transpileAnnotatedJStoC(jsCode) {
|
|
|
|
return jsCode
|
|
|
|
.replace('node.style.measure', 'node.measure')
|
|
|
|
.replace(/\.children\.length/g, '.children_count')
|
|
|
|
.replace(/\.width/g, '.dimensions[CSS_WIDTH]')
|
|
|
|
.replace(/\.height/g, '.dimensions[CSS_HEIGHT]')
|
|
|
|
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
|
|
|
.replace(/layout\[pos/g, 'layout.position[pos')
|
|
|
|
.replace(/layout\[leading/g, 'layout.position[leading')
|
|
|
|
.replace(/style\[dim/g, 'style.dimensions[dim')
|
|
|
|
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
|
|
|
.replace(/node\./g, 'node->')
|
|
|
|
.replace(/child\./g, 'child->')
|
|
|
|
.replace(/parent\./g, 'parent->')
|
|
|
|
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
|
|
|
.replace(/ === /g, ' == ')
|
2014-12-11 20:23:53 +00:00
|
|
|
.replace(/ !== /g, ' != ')
|
2015-02-17 21:12:29 -05:00
|
|
|
.replace(/\n {2}/g, '\n')
|
2014-09-18 15:15:21 -07:00
|
|
|
.replace(/\/\*\(c\)!([^*]+)\*\//g, '$1')
|
2014-09-26 16:22:44 -07:00
|
|
|
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
|
|
|
.split('\n').slice(1, -1).join('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
function makeConstDefs() {
|
2015-02-17 21:12:29 -05:00
|
|
|
/* eslint no-multi-spaces: 3 */
|
2014-09-26 16:22:44 -07:00
|
|
|
var lines = [
|
|
|
|
'#define SMALL_WIDTH ' + layoutTestUtils.textSizes.smallWidth,
|
|
|
|
'#define SMALL_HEIGHT ' + layoutTestUtils.textSizes.smallHeight,
|
|
|
|
'#define BIG_WIDTH ' + layoutTestUtils.textSizes.bigWidth,
|
|
|
|
'#define BIG_HEIGHT ' + layoutTestUtils.textSizes.bigHeight,
|
|
|
|
'#define BIG_MIN_WIDTH ' + layoutTestUtils.textSizes.bigMinWidth,
|
|
|
|
'#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"',
|
|
|
|
'#define LONG_TEXT "' + layoutTestUtils.texts.big + '"'
|
|
|
|
];
|
|
|
|
return lines.join('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
function generateFile(fileName, generatedContent) {
|
|
|
|
var content = fs.readFileSync(fileName, 'utf8').toString();
|
|
|
|
content = content.replace(new RegExp(
|
|
|
|
/\/\*\* START_GENERATED \*\*\/[\s\S]*\/\*\* END_GENERATED \*\*\//
|
|
|
|
), '/** START_GENERATED **/\n' + generatedContent + '\n /** END_GENERATED **/');
|
|
|
|
|
|
|
|
fs.writeFileSync(fileName, content);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-18 15:15:21 -07:00
|
|
|
var allTestsInC = allTests.map(printLayout);
|
|
|
|
generateFile(__dirname + '/__tests__/Layout-test.c', allTestsInC.join('\n\n'));
|
2014-09-26 16:22:44 -07:00
|
|
|
generateFile(__dirname + '/Layout-test-utils.c', makeConstDefs());
|
|
|
|
generateFile(__dirname + '/Layout.c', transpileAnnotatedJStoC(computeLayout.toString()));
|
2014-09-18 15:15:21 -07:00
|
|
|
generateFile(__dirname + '/java/src/com/facebook/csslayout/LayoutEngine.java', JavaTranspiler.transpileLayoutEngine(computeLayout.toString()));
|
|
|
|
generateFile(__dirname + '/java/tests/com/facebook/csslayout/TestConstants.java', JavaTranspiler.transpileCConstDefs(makeConstDefs()));
|
|
|
|
generateFile(__dirname + '/java/tests/com/facebook/csslayout/LayoutEngineTest.java', JavaTranspiler.transpileCTestsArray(allTestsInC));
|