Import new C source of truth css-layout
fbshipit-source-id: e866918d6c62fc1cf3a04c269f782b94db9b875a
This commit is contained in:
Родитель
93809b69c8
Коммит
fdd8552c4e
|
@ -0,0 +1,2 @@
|
|||
[cxx]
|
||||
gtest_dep = //lib/gtest:gtest
|
|
@ -0,0 +1 @@
|
|||
158950c02e1553d3a17979e74d9df020594e4d30
|
20
.eslintrc
20
.eslintrc
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"extends": "./node_modules/fbjs-scripts/eslint/.eslintrc",
|
||||
"globals": {
|
||||
"jasmine": true,
|
||||
"describe": true,
|
||||
"beforeEach": true,
|
||||
"afterEach": true,
|
||||
"spyOn": true,
|
||||
"it": true,
|
||||
"xit": true,
|
||||
"expect": true,
|
||||
"require": true,
|
||||
"global": true,
|
||||
"__dirname": true,
|
||||
"module": true,
|
||||
"console": true,
|
||||
"setTimeout": true,
|
||||
"define": true
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
a.out
|
||||
*.class
|
||||
/**/java/out/*
|
||||
/**/.idea/workspace.xml
|
||||
/lib/
|
||||
/node_modules/
|
||||
npm-debug.log
|
||||
.DS_STORE
|
||||
|
||||
/buck-cache/
|
||||
/buck-out/
|
||||
/.buckconfig.local
|
||||
/.buckd
|
||||
/lib/gtest/googletest-*/
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.DS_STORE
|
||||
|
||||
/buck-cache/
|
||||
/buck-out/
|
||||
/.buckconfig.local
|
||||
/.buckd
|
||||
/lib/gtest/googletest-*/
|
18
.travis.yml
18
.travis.yml
|
@ -1,18 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.12"
|
||||
|
||||
sudo: true
|
||||
|
||||
before_install:
|
||||
- npm install grunt-cli -g
|
||||
- sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
|
||||
- echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
|
||||
- echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get -qq install mono-devel referenceassemblies-pcl nunit
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright (c) 2014-present, 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.
|
||||
|
||||
include_defs('//CSSLAYOUT_DEFS')
|
||||
|
||||
BASE_COMPILER_FLAGS = [
|
||||
'-fno-omit-frame-pointer',
|
||||
'-fexceptions',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
]
|
||||
|
||||
GMOCK_OVERRIDE_FLAGS = [
|
||||
# gmock does not mark mocked methods as override, ignore the warnings in tests
|
||||
'-Wno-inconsistent-missing-override',
|
||||
]
|
||||
|
||||
COMPILER_FLAGS = BASE_COMPILER_FLAGS + ['-std=c11']
|
||||
TEST_COMPILER_FLAGS = BASE_COMPILER_FLAGS + GMOCK_OVERRIDE_FLAGS + ['-std=c++11']
|
||||
|
||||
cxx_library(
|
||||
name = 'CSSLayout',
|
||||
srcs = glob(['CSSLayout/*.c']),
|
||||
tests=[':CSSLayout_tests'],
|
||||
exported_headers = subdir_glob([('', 'CSSLayout/*.h')]),
|
||||
header_namespace = '',
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
deps = [],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
cxx_library(
|
||||
name = 'CSSLayoutTestUtils',
|
||||
srcs = glob(['tests/CSSLayoutTestUtils/*.c']),
|
||||
exported_headers = subdir_glob([('tests', 'CSSLayoutTestUtils/*.h')]),
|
||||
header_namespace = '',
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
deps = [
|
||||
':CSSLayout',
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
cxx_test(
|
||||
name = 'CSSLayout_tests',
|
||||
contacts = ['emilsj@fb.com'],
|
||||
srcs = glob(['tests/*.cpp']),
|
||||
compiler_flags = TEST_COMPILER_FLAGS,
|
||||
deps = [
|
||||
':CSSLayout',
|
||||
':CSSLayoutTestUtils',
|
||||
GTEST_TARGET,
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = 'CSSLayout_java',
|
||||
srcs = glob(['java/**/*.java']),
|
||||
tests=[':CSSLayout_java_tests'],
|
||||
source = '1.7',
|
||||
target = '1.7',
|
||||
deps = [
|
||||
INFER_ANNOTATIONS_TARGET,
|
||||
JSR_305_TARGET,
|
||||
],
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
java_test(
|
||||
name = 'CSSLayout_java_tests',
|
||||
srcs = glob(['tests/java/**/*.java']),
|
||||
deps = [
|
||||
':CSSLayout_java',
|
||||
JUNIT_TARGET,
|
||||
],
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
CSSLAYOUT_ROOT = '//...'
|
||||
INFER_ANNOTATIONS_TARGET = '//lib/infer-annotations:infer-annotations'
|
||||
JSR_305_TARGET = '//lib/jsr-305:jsr-305'
|
||||
JUNIT_TARGET = '//lib/junit:junit'
|
||||
GTEST_TARGET = '//lib/gtest:gtest'
|
||||
GTEST_DL_URL = 'https://github.com/google/googletest/archive/release-1.7.0.zip'
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
#ifndef __CSS_LAYOUT_INTERNAL_H
|
||||
#define __CSS_LAYOUT_INTERNAL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "CSSLayout.h"
|
||||
#include "CSSNodeList.h"
|
||||
|
||||
CSS_EXTERN_C_BEGIN
|
||||
|
||||
typedef struct CSSCachedMeasurement {
|
||||
float availableWidth;
|
||||
float availableHeight;
|
||||
CSSMeasureMode widthMeasureMode;
|
||||
CSSMeasureMode heightMeasureMode;
|
||||
|
||||
float computedWidth;
|
||||
float computedHeight;
|
||||
} CSSCachedMeasurement;
|
||||
|
||||
// This value was chosen based on empiracle data. Even the most complicated
|
||||
// layouts should not require more than 16 entries to fit within the cache.
|
||||
enum {
|
||||
CSS_MAX_CACHED_RESULT_COUNT = 16
|
||||
};
|
||||
|
||||
typedef struct CSSLayout {
|
||||
float position[4];
|
||||
float dimensions[2];
|
||||
CSSDirection direction;
|
||||
|
||||
float flexBasis;
|
||||
|
||||
// Instead of recomputing the entire layout every single time, we
|
||||
// cache some information to break early when nothing changed
|
||||
int generationCount;
|
||||
CSSDirection lastParentDirection;
|
||||
|
||||
int nextCachedMeasurementsIndex;
|
||||
CSSCachedMeasurement cachedMeasurements[CSS_MAX_CACHED_RESULT_COUNT];
|
||||
float measuredDimensions[2];
|
||||
|
||||
CSSCachedMeasurement cached_layout;
|
||||
} CSSLayout;
|
||||
|
||||
typedef struct CSSStyle {
|
||||
CSSDirection direction;
|
||||
CSSFlexDirection flexDirection;
|
||||
CSSJustify justifyContent;
|
||||
CSSAlign alignContent;
|
||||
CSSAlign alignItems;
|
||||
CSSAlign alignSelf;
|
||||
CSSPositionType positionType;
|
||||
CSSWrapType flexWrap;
|
||||
CSSOverflow overflow;
|
||||
float flex;
|
||||
float margin[6];
|
||||
float position[4];
|
||||
/**
|
||||
* You should skip all the rules that contain negative values for the
|
||||
* following attributes. For example:
|
||||
* {padding: 10, paddingLeft: -5}
|
||||
* should output:
|
||||
* {left: 10 ...}
|
||||
* the following two are incorrect:
|
||||
* {left: -5 ...}
|
||||
* {left: 0 ...}
|
||||
*/
|
||||
float padding[6];
|
||||
float border[6];
|
||||
float dimensions[2];
|
||||
float minDimensions[2];
|
||||
float maxDimensions[2];
|
||||
} CSSStyle;
|
||||
|
||||
typedef struct CSSNode {
|
||||
CSSStyle style;
|
||||
CSSLayout layout;
|
||||
int lineIndex;
|
||||
bool shouldUpdate;
|
||||
bool isTextNode;
|
||||
CSSNodeRef parent;
|
||||
CSSNodeListRef children;
|
||||
bool isDirty;
|
||||
|
||||
struct CSSNode* nextChild;
|
||||
|
||||
CSSSize (*measure)(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
|
||||
void (*print)(void *context);
|
||||
void *context;
|
||||
} CSSNode;
|
||||
|
||||
CSS_EXTERN_C_END
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
#ifndef __CSS_LAYOUT_H
|
||||
#define __CSS_LAYOUT_H
|
||||
|
||||
#include <math.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
// Not defined in MSVC++
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *)__nan)
|
||||
#endif
|
||||
|
||||
#define CSSUndefined NAN
|
||||
|
||||
#include <CSSLayout/CSSMacros.h>
|
||||
|
||||
CSS_EXTERN_C_BEGIN
|
||||
|
||||
typedef enum CSSDirection {
|
||||
CSSDirectionInherit,
|
||||
CSSDirectionLTR,
|
||||
CSSDirectionRTL,
|
||||
} CSSDirection;
|
||||
|
||||
typedef enum CSSFlexDirection {
|
||||
CSSFlexDirectionColumn,
|
||||
CSSFlexDirectionColumnReverse,
|
||||
CSSFlexDirectionRow,
|
||||
CSSFlexDirectionRowReverse,
|
||||
} CSSFlexDirection;
|
||||
|
||||
typedef enum CSSJustify {
|
||||
CSSJustifyFlexStart,
|
||||
CSSJustifyCenter,
|
||||
CSSJustifyFlexEnd,
|
||||
CSSJustifySpaceBetween,
|
||||
CSSJustifySpaceAround,
|
||||
} CSSJustify;
|
||||
|
||||
typedef enum CSSOverflow {
|
||||
CSSOverflowVisible,
|
||||
CSSOverflowHidden,
|
||||
} CSSOverflow;
|
||||
|
||||
// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
|
||||
// alignItems.
|
||||
typedef enum CSSAlign {
|
||||
CSSAlignAuto,
|
||||
CSSAlignFlexStart,
|
||||
CSSAlignCenter,
|
||||
CSSAlignFlexEnd,
|
||||
CSSAlignStretch,
|
||||
} CSSAlign;
|
||||
|
||||
typedef enum CSSPositionType {
|
||||
CSSPositionTypeRelative,
|
||||
CSSPositionTypeAbsolute,
|
||||
} CSSPositionType;
|
||||
|
||||
typedef enum CSSWrapType {
|
||||
CSSWrapTypeNoWrap,
|
||||
CSSWrapTypeWrap,
|
||||
} CSSWrapType;
|
||||
|
||||
// Note: left and top are shared between position[2] and position[4], so
|
||||
// they have to be before right and bottom.
|
||||
typedef enum CSSPosition {
|
||||
CSSPositionLeft,
|
||||
CSSPositionTop,
|
||||
CSSPositionRight,
|
||||
CSSPositionBottom,
|
||||
CSSPositionStart,
|
||||
CSSPositionEnd,
|
||||
CSSPositionCount,
|
||||
} CSSPosition;
|
||||
|
||||
typedef enum CSSMeasureMode {
|
||||
CSSMeasureModeUndefined,
|
||||
CSSMeasureModeExactly,
|
||||
CSSMeasureModeAtMost,
|
||||
CSSMeasureModeCount,
|
||||
} CSSMeasureMode;
|
||||
|
||||
typedef enum CSSDimension {
|
||||
CSSDimensionWidth,
|
||||
CSSDimensionHeight,
|
||||
} CSSDimension;
|
||||
|
||||
typedef enum CSSPrintOptions {
|
||||
CSSPrintOptionsLayout = 1,
|
||||
CSSPrintOptionsStyle = 2,
|
||||
CSSPrintOptionsChildren = 4,
|
||||
} CSSPrintOptions;
|
||||
|
||||
typedef struct CSSSize {
|
||||
float width;
|
||||
float height;
|
||||
} CSSSize;
|
||||
|
||||
typedef struct CSSNode * CSSNodeRef;
|
||||
typedef CSSSize (*CSSMeasureFunc)(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
|
||||
typedef void (*CSSPrintFunc)(void *context);
|
||||
|
||||
// CSSNode
|
||||
CSSNodeRef CSSNodeNew();
|
||||
void CSSNodeInit(CSSNodeRef node);
|
||||
void CSSNodeFree(CSSNodeRef node);
|
||||
|
||||
void CSSNodeInsertChild(CSSNodeRef node, CSSNodeRef child, unsigned int index);
|
||||
void CSSNodeRemoveChild(CSSNodeRef node, CSSNodeRef child);
|
||||
CSSNodeRef CSSNodeGetChild(CSSNodeRef node, unsigned int index);
|
||||
unsigned int CSSNodeChildCount(CSSNodeRef node);
|
||||
|
||||
void CSSNodeCalculateLayout(
|
||||
CSSNodeRef node,
|
||||
float availableWidth,
|
||||
float availableHeight,
|
||||
CSSDirection parentDirection);
|
||||
|
||||
// Mark a node as dirty. Only valid for nodes with a custom measure function set.
|
||||
// CSSLayout knows when to mark all other nodes as dirty but because nodes with measure functions
|
||||
// depends on information not known to CSSLayout they must perform this dirty marking manually.
|
||||
void CSSNodeMarkDirty(CSSNodeRef node);
|
||||
|
||||
void CSSNodePrint(CSSNodeRef node, CSSPrintOptions options);
|
||||
|
||||
bool isUndefined(float value);
|
||||
|
||||
#define CSS_NODE_PROPERTY(type, name, paramName) \
|
||||
void CSSNodeSet##name(CSSNodeRef node, type paramName); \
|
||||
type CSSNodeGet##name(CSSNodeRef node);
|
||||
|
||||
#define CSS_NODE_STYLE_PROPERTY(type, name, paramName) \
|
||||
void CSSNodeStyleSet##name(CSSNodeRef node, type paramName); \
|
||||
type CSSNodeStyleGet##name(CSSNodeRef node);
|
||||
|
||||
#define CSS_NODE_LAYOUT_PROPERTY(type, name) \
|
||||
type CSSNodeLayoutGet##name(CSSNodeRef node);
|
||||
|
||||
CSS_NODE_PROPERTY(void*, Context, context);
|
||||
CSS_NODE_PROPERTY(CSSMeasureFunc, MeasureFunc, measureFunc);
|
||||
CSS_NODE_PROPERTY(CSSPrintFunc, PrintFunc, printFunc);
|
||||
CSS_NODE_PROPERTY(bool, IsTextnode, isTextNode);
|
||||
CSS_NODE_PROPERTY(bool, ShouldUpdate, shouldUpdate);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(CSSDirection, Direction, direction);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSFlexDirection, FlexDirection, flexDirection);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSJustify, JustifyContent, justifyContent);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSAlign, AlignContent, alignContent);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSAlign, AlignItems, alignItems);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSAlign, AlignSelf, alignSelf);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSPositionType, PositionType, positionType);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSWrapType, FlexWrap, flexWrap);
|
||||
CSS_NODE_STYLE_PROPERTY(CSSOverflow, Overflow, overflow);
|
||||
CSS_NODE_STYLE_PROPERTY(float, Flex, flex);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(float, PositionLeft, positionLeft);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PositionTop, positionTop);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PositionRight, positionRight);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PositionBottom, positionBottom);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginLeft, marginLeft);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginTop, marginTop);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginRight, marginRight);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginBottom, marginBottom);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginStart, marginStart);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MarginEnd, marginEnd);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingLeft, paddingLeft);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingTop, paddingTop);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingRight, paddingRight);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingBottom, paddingBottom);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingStart, paddingStart);
|
||||
CSS_NODE_STYLE_PROPERTY(float, PaddingEnd, paddingEnd);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderLeft, borderLeft);
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderTop, borderTop);
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderRight, borderRight);
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderBottom, borderBottom);
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderStart, borderStart);
|
||||
CSS_NODE_STYLE_PROPERTY(float, BorderEnd, borderEnd);
|
||||
|
||||
CSS_NODE_STYLE_PROPERTY(float, Width, width);
|
||||
CSS_NODE_STYLE_PROPERTY(float, Height, height);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MinWidth, minWidth);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MinHeight, minHeight);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MaxWidth, maxWidth);
|
||||
CSS_NODE_STYLE_PROPERTY(float, MaxHeight, maxHeight);
|
||||
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Left);
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Top);
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Right);
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Bottom);
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Width);
|
||||
CSS_NODE_LAYOUT_PROPERTY(float, Height);
|
||||
|
||||
CSS_EXTERN_C_END
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
|
@ -7,14 +7,15 @@
|
|||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSAlign
|
||||
{
|
||||
Auto,
|
||||
FlexStart,
|
||||
Center,
|
||||
FlexEnd,
|
||||
Stretch,
|
||||
}
|
||||
}
|
||||
#ifndef __CSS_MACROS_H
|
||||
#define __CSS_MACROS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define CSS_EXTERN_C_BEGIN extern "C" {
|
||||
# define CSS_EXTERN_C_END }
|
||||
#else
|
||||
# define CSS_EXTERN_C_BEGIN
|
||||
# define CSS_EXTERN_C_END
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "CSSNodeList.h"
|
||||
|
||||
struct CSSNodeList {
|
||||
int capacity;
|
||||
int count;
|
||||
void **items;
|
||||
};
|
||||
|
||||
CSSNodeListRef CSSNodeListNew(unsigned int initialCapacity) {
|
||||
CSSNodeListRef list = malloc(sizeof(struct CSSNodeList));
|
||||
assert(list != NULL);
|
||||
|
||||
list->capacity = initialCapacity;
|
||||
list->count = 0;
|
||||
list->items = malloc(sizeof(void*) * list->capacity);
|
||||
assert(list->items != NULL);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void CSSNodeListFree(CSSNodeListRef list) {
|
||||
free(list);
|
||||
}
|
||||
|
||||
unsigned int CSSNodeListCount(CSSNodeListRef list) {
|
||||
return list->count;
|
||||
}
|
||||
|
||||
void CSSNodeListAdd(CSSNodeListRef list, CSSNodeRef node) {
|
||||
CSSNodeListInsert(list, node, list->count);
|
||||
}
|
||||
|
||||
void CSSNodeListInsert(CSSNodeListRef list, CSSNodeRef node, unsigned int index) {
|
||||
if (list->count == list->capacity) {
|
||||
list->capacity *= 2;
|
||||
list->items = realloc(list->items, sizeof(void*) * list->capacity);
|
||||
assert(list->items != NULL);
|
||||
}
|
||||
|
||||
for (unsigned int i = list->count; i > index; i--) {
|
||||
list->items[i] = list->items[i - 1];
|
||||
}
|
||||
|
||||
list->count++;
|
||||
list->items[index] = node;
|
||||
}
|
||||
|
||||
CSSNodeRef CSSNodeListRemove(CSSNodeListRef list, unsigned int index) {
|
||||
CSSNodeRef removed = list->items[index];
|
||||
list->items[index] = NULL;
|
||||
|
||||
for (unsigned int i = index; i < list->count - 1; i++) {
|
||||
list->items[i] = list->items[i + 1];
|
||||
list->items[i + 1] = NULL;
|
||||
}
|
||||
|
||||
list->count--;
|
||||
return removed;
|
||||
}
|
||||
|
||||
CSSNodeRef CSSNodeListDelete(CSSNodeListRef list, CSSNodeRef node) {
|
||||
for (unsigned int i = 0; i < list->count; i++) {
|
||||
if (list->items[i] == node) {
|
||||
return CSSNodeListRemove(list, i);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CSSNodeRef CSSNodeListGet(CSSNodeListRef list, unsigned int index) {
|
||||
return list->items[index];
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
#ifndef __CSS_NODE_LIST_H
|
||||
#define __CSS_NODE_LIST_H
|
||||
|
||||
#include <CSSLayout/CSSLayout.h>
|
||||
|
||||
CSS_EXTERN_C_BEGIN
|
||||
|
||||
typedef struct CSSNodeList * CSSNodeListRef;
|
||||
|
||||
CSSNodeListRef CSSNodeListNew(unsigned int initialCapacity);
|
||||
void CSSNodeListFree(CSSNodeListRef list);
|
||||
unsigned int CSSNodeListCount(CSSNodeListRef list);
|
||||
void CSSNodeListAdd(CSSNodeListRef list, CSSNodeRef node);
|
||||
void CSSNodeListInsert(CSSNodeListRef list, CSSNodeRef node, unsigned int index);
|
||||
CSSNodeRef CSSNodeListRemove(CSSNodeListRef list, unsigned int index);
|
||||
CSSNodeRef CSSNodeListDelete(CSSNodeListRef list, CSSNodeRef node);
|
||||
CSSNodeRef CSSNodeListGet(CSSNodeListRef list, unsigned int index);
|
||||
|
||||
CSS_EXTERN_C_END
|
||||
|
||||
#endif
|
198
Gruntfile.js
198
Gruntfile.js
|
@ -1,198 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
var path = require('path');
|
||||
var isWindows = (/^win/).test(process.platform);
|
||||
|
||||
require('load-grunt-tasks')(grunt);
|
||||
|
||||
// config
|
||||
var config = {
|
||||
delimiter: path.delimiter,
|
||||
libName: 'css-layout',
|
||||
distFolder: 'dist',
|
||||
srcFolder: 'src',
|
||||
testFolder: 'src/__tests__',
|
||||
javaLibFolder: 'src/java/lib',
|
||||
javaSource: 'src/java/tests/com/facebook/csslayout/*.java',
|
||||
javaTestFiles: 'org.junit.runner.JUnitCore com.facebook.csslayout.LayoutEngineTest com.facebook.csslayout.LayoutCachingTest com.facebook.csslayout.CSSNodeTest'
|
||||
};
|
||||
|
||||
// C compilation configuration
|
||||
if (isWindows) {
|
||||
// Windows build, assumes cl is in the path (see https://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx).
|
||||
config.cTestOutput = 'c_test.exe';
|
||||
config.cTestCompile = 'cl -nologo -Zi -Tpsrc/__tests__/Layout-test.c -Tpsrc/Layout.c -Tpsrc/Layout-test-utils.c -link -incremental:no -out:"<%= config.cTestOutput %>"';
|
||||
config.cTestExecute = '<%= config.cTestOutput %>';
|
||||
config.cTestClean = ['<%= config.cTestOutput %>', '*.obj', '*.pdb'];
|
||||
} else {
|
||||
// GCC build (OSX, Linux, ...), assumes gcc is in the path.
|
||||
config.cTestOutput = 'c_test';
|
||||
config.cTestCompile = 'gcc -std=c99 -Werror -Wno-padded src/__tests__/Layout-test.c src/Layout.c src/Layout-test-utils.c -lm -o "./<%= config.cTestOutput %>"';
|
||||
config.cTestExecute = './<%= config.cTestOutput %>';
|
||||
config.cTestClean = ['<%= config.cTestOutput %>'];
|
||||
}
|
||||
|
||||
grunt.initConfig({
|
||||
config: config,
|
||||
|
||||
mkdir: {
|
||||
dist: {
|
||||
options: {
|
||||
create: ['<%= config.distFolder %>']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clean: {
|
||||
dist: ['<%= config.distFolder %>/css-layout.*'],
|
||||
cTest: config.cTestClean,
|
||||
javaTest: ['**/*.class']
|
||||
},
|
||||
|
||||
eslint: {
|
||||
options: {
|
||||
configFile: '.eslintrc'
|
||||
},
|
||||
target: ['<%= config.srcFolder %>/**/*.js', './Gruntfile.js']
|
||||
},
|
||||
|
||||
includereplace: {
|
||||
options: {
|
||||
prefix: '// @@'
|
||||
},
|
||||
main: {
|
||||
src: '<%= config.srcFolder %>/<%= config.libName %>.js',
|
||||
dest: '<%= config.distFolder %>/<%= config.libName %>.js'
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
sourceMap: true,
|
||||
sourceMapIncludeSources: true
|
||||
},
|
||||
main: {
|
||||
files: {
|
||||
'<%= config.distFolder %>/<%= config.libName %>.min.js':
|
||||
['<%= config.distFolder %>/<%= config.libName %>.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
karma: {
|
||||
main: {
|
||||
options: {
|
||||
files: [
|
||||
'<%= config.srcFolder %>/Layout.js',
|
||||
'<%= config.srcFolder %>/Layout-test-utils.js',
|
||||
'<%= config.testFolder %>/Layout-test.js',
|
||||
'<%= config.testFolder %>/Layout-consts-test.js'
|
||||
],
|
||||
browsers: ['Chrome'],
|
||||
frameworks: ['jasmine'],
|
||||
singleRun: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
execute: {
|
||||
transpile: {
|
||||
src: ['<%= config.srcFolder %>/transpile.js']
|
||||
}
|
||||
},
|
||||
|
||||
concat: {
|
||||
options: {
|
||||
separator: '\n',
|
||||
// Replace all 'use strict' statements in the code with a single one at the top
|
||||
banner: [
|
||||
'/*',
|
||||
' * #define CSS_LAYOUT_IMPLEMENTATION',
|
||||
' * before you include this file in *one* C or C++ file to create the implementation.',
|
||||
' */\n'
|
||||
].join('\n'),
|
||||
process: function(src, filepath) {
|
||||
if (path.extname(filepath) === '.c') {
|
||||
return [
|
||||
'#ifdef CSS_LAYOUT_IMPLEMENTATION',
|
||||
src,
|
||||
'#endif // CSS_LAYOUT_IMPLEMENTATION'
|
||||
].join('\n');
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
},
|
||||
dist: {
|
||||
src: ['<%= config.srcFolder %>/Layout.h', '<%= config.srcFolder %>/Layout.c'],
|
||||
dest: '<%= config.distFolder %>/css-layout.h'
|
||||
}
|
||||
},
|
||||
|
||||
shell: {
|
||||
cCompile: {
|
||||
command: config.cTestCompile
|
||||
},
|
||||
cTestExecute: {
|
||||
command: config.cTestExecute
|
||||
},
|
||||
javaCompile: {
|
||||
command: 'javac -cp <%= config.javaLibFolder %>/junit4.jar<%= config.delimiter %><%= config.javaLibFolder %>/jsr305.jar<%= config.delimiter %><%= config.javaLibFolder %>/infer-annotations-1.4.jar' + ' -sourcepath ./src/java/src<%= config.delimiter %>./src/java/tests' + ' <%= config.javaSource %>'
|
||||
},
|
||||
javaTestExecute: {
|
||||
command: 'java -cp ./src/java/src<%= config.delimiter %>./src/java/tests<%= config.delimiter %><%= config.javaLibFolder %>/junit4.jar<%= config.delimiter %><%= config.javaLibFolder %>/infer-annotations-1.4.jar <%= config.javaTestFiles %>'
|
||||
},
|
||||
javaPackage: {
|
||||
command: 'jar cf <%= config.distFolder %>/<%= config.libName %>.jar <%= config.javaSource %>'
|
||||
},
|
||||
csharpCompile: {
|
||||
command: 'xbuild /verbosity:m /nologo src/csharp/Facebook.CSSLayout.sln /p:Configuration=Release /t:"Facebook_CSSLayout:Rebuild;Facebook_CSSLayout_Tests:Rebuild"'
|
||||
},
|
||||
csharpTestExecute: {
|
||||
command: 'nunit-console -nologo src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll'
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
files: ['src/Layout.js'],
|
||||
tasks: ['ci']
|
||||
}
|
||||
});
|
||||
|
||||
// Compiles and runs the Java tests
|
||||
grunt.registerTask('test-java', ['shell:javaCompile', 'shell:javaTestExecute', 'clean:javaTest']);
|
||||
|
||||
// Compiles and runs the CSharp tests
|
||||
grunt.registerTask('test-csharp', ['shell:csharpCompile', 'shell:csharpTestExecute']);
|
||||
|
||||
// Compiles and runs the C tests
|
||||
grunt.registerTask('test-c', ['shell:cCompile', 'shell:cTestExecute', 'clean:cTest']);
|
||||
|
||||
// Transpiles the JavaScript to C and Java, running tests
|
||||
grunt.registerTask('transpile', ['execute:transpile', 'test-c', 'test-java', 'test-csharp']);
|
||||
|
||||
// Lints and tests the JavaScritp using Chrome
|
||||
grunt.registerTask('test-javascript', ['eslint', 'karma']);
|
||||
|
||||
// Packages the JavaScript as a single UMD module and minifies
|
||||
grunt.registerTask('package-javascript', ['includereplace', 'uglify']);
|
||||
|
||||
// Packages the Java as a JAR
|
||||
grunt.registerTask('package-java', ['shell:javaPackage']);
|
||||
|
||||
// Packages the C code as a single header
|
||||
grunt.registerTask('package-c', ['concat']);
|
||||
|
||||
// Packages all languages
|
||||
grunt.registerTask('package-all', ['package-javascript', 'package-java', 'package-c']);
|
||||
|
||||
// Default build, performs the full works!
|
||||
grunt.registerTask('build', ['test-javascript', 'transpile', 'clean:dist', 'mkdir:dist', 'package-all']);
|
||||
|
||||
// The JavaScript unit tests require Chrome (they need a faithful flexbox implementation
|
||||
// to test against), so under CI this step is skipped.
|
||||
grunt.registerTask('ci', ['eslint', 'transpile', 'clean:dist', 'mkdir:dist', 'package-all']);
|
||||
|
||||
grunt.registerTask('default', ['build']);
|
||||
};
|
2
LICENSE
2
LICENSE
|
@ -2,7 +2,7 @@ BSD License
|
|||
|
||||
For css-layout software
|
||||
|
||||
Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# CSSLayout [![Build Status](https://travis-ci.org/facebook/css-layout.svg?branch=master)](https://travis-ci.org/facebook/css-layout)
|
||||
|
||||
```
|
||||
css-layout is currently in the process of big changes. If you are looking at using the latest stable version please have a look at the `deprecated` branch. This includes a js version and a C-sharp version not currently available on master.
|
||||
```
|
||||
|
||||
CSSLayout is a cross platform implementation of the flexbox specification. CSSLayout targets native mobile development and is therefor disconnected from the web browser. CSSLayout is implemented in C for portability reasons and uses JNI to expose public methods to Java.
|
||||
|
||||
See CSSLayout/CSSLayout.h for a look at the public API being exposed.
|
157
README.md
157
README.md
|
@ -1,157 +0,0 @@
|
|||
css-layout [![Build Status](https://travis-ci.org/facebook/css-layout.svg?branch=master)](https://travis-ci.org/facebook/css-layout)
|
||||
==========
|
||||
|
||||
This project implements a subset of CSS including flexbox and the box model using pure JavaScript, then transpiled to C, Java and C#. The goal is to have a small standalone library to layout elements. It doesn't rely on the DOM at all.
|
||||
|
||||
The Java, C and JavaScript version of the code is available via [npm](https://www.npmjs.com/package/css-layout) or directly from the `dist` folder of this repo. The JavaScript version is also available via [cdnjs](https://cdnjs.com/libraries/css-layout).
|
||||
|
||||
In order to make sure that the code is correct, it is developed in JavaScript using TDD where each commit adds a unit test and the associated code to make it work. All the unit tests are tested against Chrome's implementation of CSS.
|
||||
|
||||
The JavaScript version has been implemented in a way that can be easily transpiled to C and Java via regexes. The layout function doesn't do any allocation nor uses any of the dynamic aspects of JavaScript. The tests are also transpiled to make sure that the implementations are correct everywhere.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A single function `computeLayout` is exposed that
|
||||
- takes a tree of nodes: `{ style: { ... }, children: [ nodes ] }`
|
||||
- computes the layout and writes it back to the node tree.
|
||||
|
||||
For example,
|
||||
|
||||
```javascript
|
||||
// create an initial tree of nodes
|
||||
var nodeTree = {
|
||||
"style": {
|
||||
"padding": 50
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"style": {
|
||||
"padding": 10,
|
||||
"alignSelf": "stretch"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// compute the layout
|
||||
computeLayout(nodeTree);
|
||||
|
||||
// the layout information is written back to the node tree, with
|
||||
// each node now having a layout property:
|
||||
|
||||
// JSON.stringify(nodeTree, null, 2);
|
||||
{
|
||||
"style": {
|
||||
"padding": 50
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"style": {
|
||||
"padding": 10,
|
||||
"alignSelf": "stretch"
|
||||
},
|
||||
"layout": {
|
||||
"width": 20,
|
||||
"height": 20,
|
||||
"top": 50,
|
||||
"left": 50,
|
||||
"right": 50,
|
||||
"bottom": 50,
|
||||
"direction": "ltr"
|
||||
},
|
||||
"children": [],
|
||||
"lineIndex": 0
|
||||
}
|
||||
],
|
||||
"layout": {
|
||||
"width": 120,
|
||||
"height": 120,
|
||||
"top": 0,
|
||||
"left": 0,
|
||||
"right": 0,
|
||||
"bottom": 0,
|
||||
"direction": "ltr"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Supported Attributes
|
||||
--------------------
|
||||
|
||||
Name | Value
|
||||
----:|------
|
||||
width, height | positive number
|
||||
minWidth, minHeight | positive number
|
||||
maxWidth, maxHeight | positive number
|
||||
left, right, top, bottom | number
|
||||
margin, marginLeft, marginRight, marginTop, marginBottom | number
|
||||
padding, paddingLeft, paddingRight, paddingTop, paddingBottom | positive number
|
||||
borderWidth, borderLeftWidth, borderRightWidth, borderTopWidth, borderBottomWidth | positive number
|
||||
flexDirection | 'column', 'row'
|
||||
justifyContent | 'flex-start', 'center', 'flex-end', 'space-between', 'space-around'
|
||||
alignItems, alignSelf | 'flex-start', 'center', 'flex-end', 'stretch'
|
||||
flex | number
|
||||
flexWrap | 'wrap', 'nowrap'
|
||||
position | 'relative', 'absolute'
|
||||
overflow | 'visible', 'hidden'
|
||||
|
||||
- Rather than allowing arbitrary combinations of `flex-grow`, `flex-shrink`, and `flex-basis` the implementation only supports a few common combinations expressed as a single number using the `flex` attribute:
|
||||
|
||||
css-layout `flex` value | W3C `flex` short-hand equivalent
|
||||
---|---
|
||||
n (where n > 0) | n 0 0
|
||||
0 | 0 0 auto
|
||||
-1 | 0 1 auto
|
||||
|
||||
- `inherit` value is not implemented because it's a way to disambiguate between multiple colliding rules. This should be done in a pre-processing step, not in the actual layout algorithm.
|
||||
|
||||
|
||||
|
||||
Default values
|
||||
--------------
|
||||
Since we are only using flexbox, we can use defaults that are much more sensible. This is the configuration to use in order to get the same behavior using the DOM and CSS. You can try those default settings with the [following JSFiddle](http://jsfiddle.net/vjeux/y11txxv9/).
|
||||
|
||||
```css
|
||||
div, span {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
flex-shrink: 0;
|
||||
align-content: flex-start;
|
||||
|
||||
border: 0 solid black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
```
|
||||
|
||||
- `box-sizing: border-box` is the most convenient way to express the relation between `width` and `borderWidth`.
|
||||
- Everything is `display: flex` by default. All the behaviors of `block` and `inline-block` can be expressed in term of `flex` but not the opposite.
|
||||
- All the flex elements are oriented from top to bottom, left to right and do not shrink. This is how things are laid out using the default CSS settings and what you'd expect.
|
||||
- Everything is `position: relative`. This makes `position: absolute` target the direct parent and not some parent which is either `relative` or `absolute`. If you want to position an element relative to something else, you should move it in the DOM instead of relying of CSS. It also makes `top, left, right, bottom` do something when not specifying `position: absolute`.
|
||||
|
||||
Native Usage Notes
|
||||
------------------
|
||||
|
||||
The C equivalent of `computeLayout` is [`layoutNode`](dist/css-layout.h#L1378).
|
||||
|
||||
In order for layout to properly layout reflowable text, the `measure` function must be set on the `css_node` structure. The property can be found in [`css-layout.h`](dist/css-layout.h#L146). This function must take a void pointer to a `context` that will affect the size of the node and the `width` as computed by the layout engine, and must return a `css_dim_t` structure defining the actual needed size of the node. For the most part, the `context` field can be the text inside the node. No C implementation of this function is provided in provided - it depends on your use of css-layout. However an implementation of the function in JavaScript can be used for reference in the [test utilities](src/Layout-test-utils.js#L383).
|
||||
|
||||
Development
|
||||
-----------
|
||||
|
||||
The core logic resides with `Layout.js`, which is transpiled into equivalent C and Java implementations.
|
||||
|
||||
The JavaScript build process is managed via Grunt. The build performs linting, runs the tests against Chrome, transpiles and packages the code (JavaScript and Java) into the `dist` folder. For JavaScript, the build output uses the Universal Module Format (UMD) so that it can be used via AMD / RequireJS, CommonJS or included directly into an HTML page.
|
||||
|
||||
While developing you can just run the lint / Chrome-based tests a follows:
|
||||
|
||||
```
|
||||
grunt test-javascript
|
||||
```
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<!--This file represents the results of running a test suite-->
|
||||
<test-results name="src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll" total="0" failures="0" not-run="0" date="2016-07-08" time="14:42:41">
|
||||
<environment nunit-version="2.4.8.0" clr-version="4.0.30319.17020" os-version="Unix 15.5.0.0" platform="Unix" cwd="/Volumes/Source/css-layout" machine-name="emilsj-pro" user="emilsj" user-domain="emilsj-pro" />
|
||||
<culture-info current-culture="en-US" current-uiculture="en-US" />
|
||||
<test-suite name="src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll" success="True" time="0.001" asserts="0">
|
||||
<results />
|
||||
</test-suite>
|
||||
</test-results>
|
|
@ -1,20 +0,0 @@
|
|||
Releases can be found on [npm](https://www.npmjs.com/package/css-layout).
|
||||
|
||||
#Release Process
|
||||
|
||||
```bash
|
||||
# Ensure that the local codebase is up to date
|
||||
git fetch upstream master && git checkout FETCH_HEAD
|
||||
|
||||
# build the latest version of the library
|
||||
grunt
|
||||
|
||||
# increment the version number and tag the release
|
||||
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease]
|
||||
|
||||
# push the the commit and tag back to upstream
|
||||
git push --tags upstream HEAD:master
|
||||
|
||||
# publish this new version to npm
|
||||
npm publish
|
||||
```
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,195 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function __transpileToCSharpCommon(code) {
|
||||
return code
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace(/undefined/g, 'null')
|
||||
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
||||
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
|
||||
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
|
||||
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
||||
.replace(/CSS_POSITION_/g, 'CSSPositionType.')
|
||||
.replace(/CSS_OVERFLOW_/g, 'CSSOverflow.')
|
||||
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
||||
.replace(/css_direction_t/g, 'CSSDirection')
|
||||
.replace(/css_align_t/g, 'CSSAlign')
|
||||
.replace(/css_justify_t/g, 'CSSJustify')
|
||||
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
|
||||
.replace(/css_dim_t/g, 'MeasureOutput')
|
||||
.replace(/bool/g, 'boolean')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[POSITION_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[POSITION_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[POSITION_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[POSITION_BOTTOM')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/(style|layout)\.width/g, '$1.dimensions[DIMENSION_WIDTH]')
|
||||
.replace(/(style|layout)\.height/g, '$1.dimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measuredDimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measuredDimensions[DIMENSION_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measuredDimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1.style.positionType')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent')
|
||||
.replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)')
|
||||
.replace(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '($1.style.dimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '($1.layout.measuredDimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)')
|
||||
.replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.measuredDimensions[dim[$3]] - ($2.style.positionType == CSSPositionType.Absolute ? 0 : $2.layout.measuredDimensions[dim[$3]]) - $2.layout.position[pos[$3]]')
|
||||
.replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex != 0\)')
|
||||
.replace(/isFlexWrap\((.+?)\)/g, '\($1.style.flexWrap == CSSWrap.WRAP\)')
|
||||
.replace(/getPaddingAndBorderAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingPaddingAndBorder($1, $2) + getTrailingPaddingAndBorder($1, $2)\)')
|
||||
.replace(/getMarginAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getLeadingPadding($1, $2) + getLeadingBorder($1, $2)\)')
|
||||
.replace(/getTrailingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getTrailingPadding($1, $2) + getTrailingBorder($1, $2)\)')
|
||||
.replace(/getDimWithMargin\((.+?),\s*(.+?)\)/g, '\($1.layout.measuredDimensions[dim[$2]] + getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/isRowDirection\((.+?)\)/g, '\($1 == CSS_FLEX_DIRECTION_ROW || $1 == CSS_FLEX_DIRECTION_ROW_REVERSE\)')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\)/g, 'Assertions.assertCondition($1, "$2")')
|
||||
.replace(/isUndefined\((.+?)\)/g, 'float.IsNaN\($1\)')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1.style.overflow')
|
||||
.replace(/layoutNodeInternal\((.+?)\)/g, 'layoutNodeInternal(layoutContext, $1)')
|
||||
.replace(/style\.position\[CSS_/g, 'style.position[POSITION_')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '')
|
||||
.replace(/var\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
|
||||
// additional case conversions
|
||||
|
||||
.replace(/(CSSConstants|CSSWrap|CSSJustify|CSSMeasureMode|CSSAlign|CSSPositionType|CSSOverflow)\.([_A-Z]+)/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.' + constantToPascalCase(match2);
|
||||
});
|
||||
}
|
||||
|
||||
function __transpileSingleTestToCSharp(code) {
|
||||
return __transpileToCSharpCommon(code)
|
||||
.replace(/CSS_DIRECTION_/g, 'CSSDirection.')
|
||||
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
||||
.replace(/CSS_WRAP/g, 'CSSWrap.WRAP')
|
||||
.replace(/new_test_css_node/g, 'new TestCSSNode')
|
||||
.replace(// style.position[CSS_TOP] => style.position[CSSLayout.POSITION_TOP]
|
||||
/(style|layout)\.position\[CSS_(LEFT|TOP|RIGHT|BOTTOM)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.position[POSITION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.dimensions[CSS_WIDTH] => style.dimensions[CSSLayout.DIMENSION_WIDTH]
|
||||
/(style|layout)\.dimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.dimensions[DIMENSION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.maxDimensions[CSS_WIDTH] => style.maxWidth
|
||||
/(style|layout)\.maxDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.max' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.minDimensions[CSS_WIDTH] => style.minWidth
|
||||
/(style|layout)\.minDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.min' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] = 12.3 => style.margin[Spacing.TOP].set(12.3)
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]\s+=\s+(-?[\.\d]+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
var propertyCap = match1.charAt(0).toUpperCase() + match1.slice(1);
|
||||
return 'set' + propertyCap + '(Spacing.' + match2 + ', ' + match3 + ')';
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] => style.margin[Spacing.TOP]
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return 'style.' + match1 + '.get(Spacing.' + match2 + ')';
|
||||
})
|
||||
.replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)')
|
||||
.replace(/init_css_node_children/g, 'addChildren')
|
||||
.replace(/css_node_t(\s)\*/g, 'TestCSSNode$1')
|
||||
.replace(/\->/g, '.')
|
||||
.replace(/(\d+\.\d+)/g, '$1f')
|
||||
.replace(// style.flex_direction => style.flexDirection
|
||||
/style\.([^_\[\]\s]+)_(\w)(\w+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
return 'style.' + match1 + match2.toUpperCase() + match3;
|
||||
})
|
||||
.replace(/(\w+)\.measure\s+=\s+.+/g, '$1.setMeasureFunction(sTestMeasureFunction);')
|
||||
|
||||
// additional case conversions
|
||||
|
||||
.replace(/(CSSWrap|CSSFlexDirection)\.([_A-Z]+)/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.' + constantToPascalCase(match2);
|
||||
});
|
||||
}
|
||||
|
||||
function indent(code) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map(function(line) { return ' ' + line; })
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
function constantToPascalCase(str) {
|
||||
return str[0] + str.substr(1)
|
||||
.toLowerCase()
|
||||
.replace(/_(.)/g,
|
||||
function(_, m) { return m.toUpperCase(); });
|
||||
}
|
||||
|
||||
var CSharpTranspiler = {
|
||||
transpileLayoutEngine: function(code) {
|
||||
return indent(
|
||||
__transpileToCSharpCommon(code)
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.getChildCount()')
|
||||
.replace(/node.children\[i\]/g, 'node.getChildAt(i)')
|
||||
.replace(/node.children\[j\]/g, 'node.getChildAt(j)')
|
||||
.replace(/fmaxf/g, 'Math.Max')
|
||||
.replace(/fminf/g, 'Math.Min')
|
||||
.replace(/\/\*\([^\/]+\*\/\n/g, '') // remove comments for other languages
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/css_node_t\*/g, 'CSSNode'));
|
||||
},
|
||||
|
||||
transpileCConstDefs: function(cConstDefs) {
|
||||
return indent(
|
||||
cConstDefs
|
||||
.replace(/#define\s+(\w+)\s+(\"[^\"]+\")/g, 'public static readonly string $1 = $2;')
|
||||
.replace(/#define\s+(\w+)\s+(.+)/g, 'public static readonly float $1 = $2f;'));
|
||||
},
|
||||
|
||||
transpileCTestsArray: function(allTestsInC) {
|
||||
var allTestsInCSharp = [];
|
||||
for (var i = 0; i < allTestsInC.length; i++) {
|
||||
allTestsInCSharp[i] =
|
||||
' [Test]\n' +
|
||||
' public void TestCase' + i + '()\n' +
|
||||
__transpileSingleTestToCSharp(allTestsInC[i]);
|
||||
}
|
||||
return allTestsInCSharp.join('\n\n');
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = CSharpTranspiler;
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function __transpileToJavaCommon(code) {
|
||||
return code
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace(/undefined/g, 'null')
|
||||
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
|
||||
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
|
||||
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
|
||||
.replace(/CSS_ALIGN_/g, 'CSSAlign.')
|
||||
.replace(/CSS_POSITION_/g, 'CSSPositionType.')
|
||||
.replace(/CSS_OVERFLOW_/g, 'CSSOverflow.')
|
||||
.replace(/css_flex_direction_t/g, 'CSSFlexDirection')
|
||||
.replace(/css_direction_t/g, 'CSSDirection')
|
||||
.replace(/css_align_t/g, 'CSSAlign')
|
||||
.replace(/css_justify_t/g, 'CSSJustify')
|
||||
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
|
||||
.replace(/css_dim_t/g, 'MeasureOutput')
|
||||
.replace(/bool/g, 'boolean')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[POSITION_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[POSITION_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[POSITION_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[POSITION_BOTTOM')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/(style|layout)\.width/g, '$1.dimensions[DIMENSION_WIDTH]')
|
||||
.replace(/(style|layout)\.height/g, '$1.dimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/layout\[dim/g, 'layout.dimensions[dim')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measuredDimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measuredDimensions[DIMENSION_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measuredDimensions[DIMENSION_HEIGHT]')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1.style.positionType')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent')
|
||||
.replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)')
|
||||
.replace(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '($1.style.dimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '($1.layout.measuredDimensions[dim[$2]] >= 0.0)')
|
||||
.replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)')
|
||||
.replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.measuredDimensions[dim[$3]] - ($2.style.positionType == CSSPositionType.ABSOLUTE ? 0 : $2.layout.measuredDimensions[dim[$3]]) - $2.layout.position[pos[$3]]')
|
||||
.replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex != 0\)')
|
||||
.replace(/isFlexWrap\((.+?)\)/g, '\($1.style.flexWrap == CSSWrap.WRAP\)')
|
||||
.replace(/getPaddingAndBorderAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingPaddingAndBorder($1, $2) + getTrailingPaddingAndBorder($1, $2)\)')
|
||||
.replace(/getMarginAxis\((.+?),\s*(.+?)\)/g, '\(getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getLeadingPadding($1, $2) + getLeadingBorder($1, $2)\)')
|
||||
.replace(/getTrailingPaddingAndBorder\((.+?),\s*(.+?)\)/g, '\(getTrailingPadding($1, $2) + getTrailingBorder($1, $2)\)')
|
||||
.replace(/getDimWithMargin\((.+?),\s*(.+?)\)/g, '\($1.layout.measuredDimensions[dim[$2]] + getLeadingMargin($1, $2) + getTrailingMargin($1, $2)\)')
|
||||
.replace(/getLeadingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingMargin\((.+?),\s*(.+?)\)/g, '$1.style.margin.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingPadding\((.+?),\s*(.+?)\)/g, '$1.style.padding.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/getLeadingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(leadingSpacing[$2], leading[$2])')
|
||||
.replace(/getTrailingBorder\((.+?),\s*(.+?)\)/g, '$1.style.border.getWithFallback(trailingSpacing[$2], trailing[$2])')
|
||||
.replace(/isRowDirection\((.+?)\)/g, '\($1 == CSS_FLEX_DIRECTION_ROW || $1 == CSS_FLEX_DIRECTION_ROW_REVERSE\)')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\)/g, 'Assertions.assertCondition($1, "$2")')
|
||||
.replace(/isUndefined\((.+?)\)/g, 'Float.isNaN\($1\)')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1.style.overflow')
|
||||
.replace(/layoutNodeInternal\((.+?)\)/g, 'layoutNodeInternal(layoutContext, $1)')
|
||||
.replace(/style\.position\[CSS_/g, 'style.position[POSITION_')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '')
|
||||
.replace(/var\/\*\(java\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '$1');
|
||||
}
|
||||
|
||||
function __transpileSingleTestToJava(code) {
|
||||
return __transpileToJavaCommon(code)
|
||||
.replace(/CSS_DIRECTION_/g, 'CSSDirection.')
|
||||
.replace(/CSS_FLEX_DIRECTION_/g, 'CSSFlexDirection.')
|
||||
.replace(/CSS_WRAP/g, 'CSSWrap.WRAP')
|
||||
.replace(/new_test_css_node/g, 'new TestCSSNode')
|
||||
.replace(// style.position[CSS_TOP] => style.position[CSSLayout.POSITION_TOP]
|
||||
/(style|layout)\.position\[CSS_(LEFT|TOP|RIGHT|BOTTOM)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.position[POSITION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.dimensions[CSS_WIDTH] => style.dimensions[CSSLayout.DIMENSION_WIDTH]
|
||||
/(style|layout)\.dimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.dimensions[DIMENSION_' + match2 + ']';
|
||||
})
|
||||
.replace(// style.maxDimensions[CSS_WIDTH] => style.maxWidth
|
||||
/(style|layout)\.maxDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.max' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.minDimensions[CSS_WIDTH] => style.minWidth
|
||||
/(style|layout)\.minDimensions\[CSS_(WIDTH|HEIGHT)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return match1 + '.min' + match2.substr(0, 1).toUpperCase() + match2.substr(1).toLowerCase();
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] = 12.3 => style.margin[Spacing.TOP].set(12.3)
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]\s+=\s+(-?[\.\d]+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
var propertyCap = match1.charAt(0).toUpperCase() + match1.slice(1);
|
||||
return 'set' + propertyCap + '(Spacing.' + match2 + ', ' + match3 + ')';
|
||||
})
|
||||
.replace(// style.margin[CSS_TOP] => style.margin[Spacing.TOP]
|
||||
/style\.(margin|border|padding)\[CSS_(TOP|BOTTOM|LEFT|RIGHT|START|END)\]/g,
|
||||
function(str, match1, match2) {
|
||||
return 'style.' + match1 + '.get(Spacing.' + match2 + ')';
|
||||
})
|
||||
.replace(/get_child\(.*context\,\s([^\)]+)\)/g, 'getChildAt($1)')
|
||||
.replace(/init_css_node_children/g, 'addChildren')
|
||||
.replace(/css_node_t(\s)\*/g, 'TestCSSNode$1')
|
||||
.replace(/\->/g, '.')
|
||||
.replace(/(\d+\.\d+)/g, '$1f')
|
||||
.replace(// style.flex_direction => style.flexDirection
|
||||
/style\.([^_\[\]\s]+)_(\w)(\w+)/g,
|
||||
function(str, match1, match2, match3) {
|
||||
return 'style.' + match1 + match2.toUpperCase() + match3;
|
||||
})
|
||||
.replace(/(\w+)\.measure\s+=\s+.+/g, '$1.setMeasureFunction(sTestMeasureFunction);');
|
||||
}
|
||||
|
||||
function indent(code) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map(function(line) { return ' ' + line; })
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
var JavaTranspiler = {
|
||||
transpileLayoutEngine: function(code) {
|
||||
return indent(
|
||||
__transpileToJavaCommon(code)
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/\.children\.length/g, '.getChildCount()')
|
||||
.replace(/node.children\[i\]/g, 'node.getChildAt(i)')
|
||||
.replace(/node.children\[j\]/g, 'node.getChildAt(j)')
|
||||
.replace(/fmaxf/g, 'Math.max')
|
||||
.replace(/fminf/g, 'Math.min')
|
||||
.replace(/\/\*\([^\/]+\*\/\n/g, '') // remove comments for other languages
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/css_node_t\*/g, 'CSSNode'));
|
||||
},
|
||||
|
||||
transpileCConstDefs: function(cConstDefs) {
|
||||
return indent(
|
||||
cConstDefs
|
||||
.replace(/#define\s+(\w+)\s+(\"[^\"]+\")/g, 'public static final String $1 = $2;')
|
||||
.replace(/#define\s+(\w+)\s+(.+)/g, 'public static final float $1 = $2f;'));
|
||||
},
|
||||
|
||||
transpileCTestsArray: function(allTestsInC) {
|
||||
var allTestsInJava = [];
|
||||
for (var i = 0; i < allTestsInC.length; i++) {
|
||||
allTestsInJava[i] =
|
||||
' @Test\n' +
|
||||
' public void testCase' + i + '()\n' +
|
||||
__transpileSingleTestToJava(allTestsInC[i]);
|
||||
}
|
||||
return allTestsInJava.join('\n\n');
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = JavaTranspiler;
|
||||
}
|
|
@ -1,216 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Layout-test-utils.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <float.h>
|
||||
#define isnan _isnan
|
||||
|
||||
/* define fmaxf & fminf if < VC12 */
|
||||
#if _MSC_VER < 1800
|
||||
__forceinline const float fmaxf(const float a, const float b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
__forceinline const float fminf(const float a, const float b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** START_GENERATED **/
|
||||
#define SMALL_WIDTH 35
|
||||
#define SMALL_HEIGHT 18
|
||||
#define BIG_WIDTH 172
|
||||
#define BIG_HEIGHT 36
|
||||
#define BIG_MIN_WIDTH 100
|
||||
#define SMALL_TEXT "small"
|
||||
#define LONG_TEXT "loooooooooong with space"
|
||||
#define MEASURE_WITH_RATIO_2 "measureWithRatio2"
|
||||
#define MEASURE_WITH_MATCH_PARENT "measureWithMatchParent"
|
||||
/** END_GENERATED **/
|
||||
|
||||
typedef struct failed_test_t {
|
||||
struct failed_test_t *next;
|
||||
const char *name;
|
||||
css_node_t *style;
|
||||
css_node_t *expected;
|
||||
} failed_test_t;
|
||||
|
||||
static failed_test_t *failed_test_head = NULL;
|
||||
static failed_test_t *failed_test_tail = NULL;
|
||||
static void add_failed_test(const char *name, css_node_t *style, css_node_t *expected) {
|
||||
failed_test_t *failed_test = (failed_test_t *)malloc(sizeof(failed_test_t));
|
||||
failed_test->next = NULL;
|
||||
failed_test->name = name;
|
||||
failed_test->style = style;
|
||||
failed_test->expected = expected;
|
||||
|
||||
if (!failed_test_head) {
|
||||
failed_test_head = failed_test;
|
||||
failed_test_tail = failed_test;
|
||||
} else {
|
||||
failed_test_tail->next = failed_test;
|
||||
failed_test_tail = failed_test;
|
||||
}
|
||||
}
|
||||
|
||||
static bool eq(float a, float b) {
|
||||
return fabs(a - b) < 0.0001;
|
||||
}
|
||||
|
||||
static bool are_layout_equal(css_node_t *a, css_node_t *b) {
|
||||
if (!eq(a->layout.dimensions[CSS_WIDTH], b->layout.dimensions[CSS_WIDTH]) ||
|
||||
!eq(a->layout.dimensions[CSS_HEIGHT], b->layout.dimensions[CSS_HEIGHT]) ||
|
||||
!eq(a->layout.position[CSS_TOP], b->layout.position[CSS_TOP]) ||
|
||||
!eq(a->layout.position[CSS_LEFT], b->layout.position[CSS_LEFT]) ||
|
||||
!eq(a->children_count, b->children_count)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a->children_count; ++i) {
|
||||
if (!are_layout_equal(a->get_child(a->context, i), b->get_child(b->context, i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode) {
|
||||
const char *text = (const char *)context;
|
||||
css_dim_t dim;
|
||||
if (strcmp(text, SMALL_TEXT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 1000000;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = SMALL_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
if (strcmp(text, LONG_TEXT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 1000000;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
|
||||
dim.dimensions[CSS_HEIGHT] = width >= BIG_WIDTH ? SMALL_HEIGHT : BIG_HEIGHT;
|
||||
return dim;
|
||||
}
|
||||
|
||||
if (strcmp(text, MEASURE_WITH_RATIO_2) == 0) {
|
||||
if (widthMode != CSS_MEASURE_MODE_UNDEFINED) {
|
||||
dim.dimensions[CSS_WIDTH] = width;
|
||||
dim.dimensions[CSS_HEIGHT] = width * 2;
|
||||
} else if (heightMode != CSS_MEASURE_MODE_UNDEFINED) {
|
||||
dim.dimensions[CSS_WIDTH] = height * 2;
|
||||
dim.dimensions[CSS_HEIGHT] = height;
|
||||
} else {
|
||||
dim.dimensions[CSS_WIDTH] = 99999;
|
||||
dim.dimensions[CSS_HEIGHT] = 99999;
|
||||
}
|
||||
return dim;
|
||||
}
|
||||
|
||||
if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) {
|
||||
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
width = 99999;
|
||||
}
|
||||
if (heightMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||
height = 99999;
|
||||
}
|
||||
dim.dimensions[CSS_WIDTH] = width;
|
||||
dim.dimensions[CSS_HEIGHT] = height;
|
||||
return dim;
|
||||
}
|
||||
|
||||
// Should not go here
|
||||
dim.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
|
||||
dim.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
|
||||
return dim;
|
||||
}
|
||||
|
||||
static int test_ran_count = 0;
|
||||
void test(const char *name, css_node_t *style, css_node_t *expected_layout) {
|
||||
++test_ran_count;
|
||||
layoutNode(style, CSS_UNDEFINED, CSS_UNDEFINED, (css_direction_t)-1);
|
||||
|
||||
if (!are_layout_equal(style, expected_layout)) {
|
||||
printf("%sF%s", "\x1B[31m", "\x1B[0m");
|
||||
add_failed_test(name, style, expected_layout);
|
||||
} else {
|
||||
printf("%s.%s", "\x1B[32m", "\x1B[0m");
|
||||
free_css_node(style);
|
||||
free_css_node(expected_layout);
|
||||
}
|
||||
}
|
||||
|
||||
int tests_finished() {
|
||||
failed_test_t *failed_test = failed_test_head;
|
||||
printf("\n");
|
||||
|
||||
int tests_failed = 0;
|
||||
while (failed_test) {
|
||||
printf("%sFAIL%s %s\n", "\x1B[31m", "\x1B[0m", failed_test->name);
|
||||
|
||||
printf("Input: ");
|
||||
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
|
||||
printf("Output: ");
|
||||
print_css_node(failed_test->style, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
||||
|
||||
printf("Expected: ");
|
||||
print_css_node(failed_test->expected, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
|
||||
|
||||
free_css_node(failed_test->style);
|
||||
free_css_node(failed_test->expected);
|
||||
|
||||
failed_test_t *next_failed_test = failed_test->next;
|
||||
free(failed_test);
|
||||
failed_test = next_failed_test;
|
||||
|
||||
tests_failed++;
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
if (tests_failed > 0) {
|
||||
printf("TESTS FAILED: %d\n", tests_failed);
|
||||
return 1;
|
||||
} else {
|
||||
printf("ALL TESTS PASSED: %d tests ran.\n", test_ran_count);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static css_node_t* get_child(void *context, int i) {
|
||||
css_node_t* children = (css_node_t*)context;
|
||||
return &children[i];
|
||||
}
|
||||
|
||||
static bool is_dirty(void *context) {
|
||||
(void)context; // remove unused warning
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_test_css_node(css_node_t *node) {
|
||||
node->get_child = get_child;
|
||||
node->is_dirty = is_dirty;
|
||||
}
|
||||
|
||||
css_node_t *new_test_css_node(void) {
|
||||
css_node_t *node = new_css_node();
|
||||
init_test_css_node(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
void init_css_node_children(css_node_t *node, int children_count) {
|
||||
node->context = calloc((size_t)children_count, sizeof(css_node_t));
|
||||
for (int i = 0; i < children_count; ++i) {
|
||||
init_css_node(node->get_child(node->context, i));
|
||||
init_test_css_node(node->get_child(node->context, i));
|
||||
}
|
||||
node->children_count = children_count;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Layout.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void test(const char *name, css_node_t *style, css_node_t *expected_layout);
|
||||
int tests_finished(void);
|
||||
css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
|
||||
void init_css_node_children(css_node_t *node, int children_count);
|
||||
css_node_t *new_test_css_node(void);
|
|
@ -1,604 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
/* globals document, computeLayout, navigator */
|
||||
|
||||
var layoutTestUtils = (function() {
|
||||
|
||||
//
|
||||
// Sets the test cases precision, by default set to 1.0, aka pixel precision
|
||||
// (assuming the browser does pixel snapping - and that we're ok with being
|
||||
// 'only' pixel perfect).
|
||||
//
|
||||
// Set it to '10' for .1 precision, etc... in theory the browser is doing
|
||||
// 'pixel' snapping so 1.0 should do, the code is left for clarity...
|
||||
//
|
||||
// Set it to undefined to disable and use full precision.
|
||||
//
|
||||
var testMeasurePrecision = 1.0;
|
||||
|
||||
if (typeof jasmine !== 'undefined') {
|
||||
jasmine.matchersUtil.buildFailureMessage = function() {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
var matcherName = args[0];
|
||||
var isNot = args[1];
|
||||
var actual = args[2];
|
||||
var expected = args.slice(3);
|
||||
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
|
||||
|
||||
var pp = function(node) {
|
||||
return jasmine.pp(node)
|
||||
.replace(/([\{\[]) /g, '$1')
|
||||
.replace(/ ([\}\]:])/g, '$1');
|
||||
};
|
||||
|
||||
var message = 'Expected ' +
|
||||
pp(actual) +
|
||||
(isNot ? ' not ' : ' ') +
|
||||
'\n' +
|
||||
englishyPredicate;
|
||||
|
||||
if (expected.length > 0) {
|
||||
for (var i = 0; i < expected.length; i++) {
|
||||
if (i > 0) {
|
||||
message += ',';
|
||||
}
|
||||
message += ' ' + pp(expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return message + '.';
|
||||
};
|
||||
}
|
||||
|
||||
var _cachedIframe;
|
||||
|
||||
function renderIframe() {
|
||||
var iframe = document.createElement('iframe');
|
||||
document.body.appendChild(iframe);
|
||||
return iframe;
|
||||
}
|
||||
|
||||
function getIframe(iframe) {
|
||||
if (_cachedIframe) {
|
||||
return _cachedIframe;
|
||||
}
|
||||
|
||||
var doc = iframe.contentDocument;
|
||||
|
||||
if (doc.readyState === 'complete') {
|
||||
var style = document.createElement('style');
|
||||
style.textContent = (function() {/*
|
||||
body, div {
|
||||
box-sizing: border-box;
|
||||
border: 0 solid black;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
align-items: stretch;
|
||||
-webkit-align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
-webkit-justify-content: flex-start;
|
||||
flex-shrink: 0;
|
||||
-webkit-flex-shrink: 0;
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
hack to ignore three hundred px width of the body {}
|
||||
body > div {
|
||||
align-self: flex-start;
|
||||
}
|
||||
*/} + '').slice(15, -4);
|
||||
doc.head.appendChild(style);
|
||||
_cachedIframe = iframe;
|
||||
return iframe;
|
||||
} else {
|
||||
setTimeout(getIframe.bind(null, iframe), 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
var iframe = renderIframe();
|
||||
getIframe(iframe);
|
||||
}
|
||||
|
||||
if (typeof computeLayout === 'object') {
|
||||
var fillNodes = computeLayout.fillNodes;
|
||||
var realComputeLayout = computeLayout.computeLayout;
|
||||
var canUseCachedMeasurement = computeLayout.canUseCachedMeasurement;
|
||||
}
|
||||
|
||||
function extractNodes(node) {
|
||||
var keysToCopy = [
|
||||
'width',
|
||||
'height',
|
||||
'left',
|
||||
'top'
|
||||
];
|
||||
var layout = {};
|
||||
keysToCopy.forEach(function(key) {
|
||||
layout[key] = node.layout[key];
|
||||
});
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
layout.children = node.children.map(extractNodes);
|
||||
} else {
|
||||
delete node.children;
|
||||
}
|
||||
|
||||
delete node.layout;
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
function roundLayout(layout) {
|
||||
// Chrome rounds all the numbers with a precision of 1/64
|
||||
// Reproduce the same behavior
|
||||
function round(number) {
|
||||
var floored = Math.floor(number);
|
||||
var decimal = number - floored;
|
||||
if (decimal === 0) {
|
||||
return number;
|
||||
}
|
||||
var minDifference = Infinity;
|
||||
var minDecimal = Infinity;
|
||||
for (var i = 1; i < 64; ++i) {
|
||||
var roundedDecimal = i / 64;
|
||||
var difference = Math.abs(roundedDecimal - decimal);
|
||||
if (difference < minDifference) {
|
||||
minDifference = difference;
|
||||
minDecimal = roundedDecimal;
|
||||
}
|
||||
}
|
||||
return floored + minDecimal;
|
||||
}
|
||||
|
||||
function rec(layout) {
|
||||
layout.top = round(layout.top);
|
||||
layout.left = round(layout.left);
|
||||
layout.width = round(layout.width);
|
||||
layout.height = round(layout.height);
|
||||
if (layout.children) {
|
||||
for (var i = 0; i < layout.children.length; ++i) {
|
||||
rec(layout.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rec(layout);
|
||||
return layout;
|
||||
}
|
||||
|
||||
function capitalizeFirst(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
function computeCSSLayout(rootNode) {
|
||||
fillNodes(rootNode);
|
||||
realComputeLayout(rootNode);
|
||||
return roundLayout(extractNodes(rootNode));
|
||||
}
|
||||
|
||||
function computeDOMLayout(node) {
|
||||
var body = getIframe().contentDocument.body;
|
||||
|
||||
function setStyle(div, name, value) {
|
||||
div.style['-webkit-' + name] = value;
|
||||
div.style['webkit' + capitalizeFirst(name)] = value;
|
||||
div.style[name] = value;
|
||||
}
|
||||
|
||||
function transfer(div, node, name, ext) {
|
||||
if (name in node.style) {
|
||||
var value = node.style[name] + (ext || '');
|
||||
setStyle(div, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
function transferSpacing(div, node, type, suffix) {
|
||||
transfer(div, node, type + suffix, 'px');
|
||||
transfer(div, node, type + 'Left' + suffix, 'px');
|
||||
transfer(div, node, type + 'Top' + suffix, 'px');
|
||||
transfer(div, node, type + 'Bottom' + suffix, 'px');
|
||||
transfer(div, node, type + 'Right' + suffix, 'px');
|
||||
transfer(div, node, type + 'Start' + suffix, 'px');
|
||||
transfer(div, node, type + 'End' + suffix, 'px');
|
||||
}
|
||||
|
||||
function transferFlex(div, node) {
|
||||
if ('flex' in node.style) {
|
||||
var flex = node.style.flex;
|
||||
var resolvedFlex = (
|
||||
flex < 0 ? '0 1 auto' :
|
||||
flex > 0 ? (flex + ' 0 0') :
|
||||
'0 0 auto'
|
||||
);
|
||||
setStyle(div, 'flex', resolvedFlex);
|
||||
}
|
||||
}
|
||||
|
||||
function renderNode(parent, node) {
|
||||
var div = document.createElement('div');
|
||||
transfer(div, node, 'width', 'px');
|
||||
transfer(div, node, 'height', 'px');
|
||||
transfer(div, node, 'minWidth', 'px');
|
||||
transfer(div, node, 'minHeight', 'px');
|
||||
transfer(div, node, 'maxWidth', 'px');
|
||||
transfer(div, node, 'maxHeight', 'px');
|
||||
transfer(div, node, 'top', 'px');
|
||||
transfer(div, node, 'left', 'px');
|
||||
transfer(div, node, 'right', 'px');
|
||||
transfer(div, node, 'bottom', 'px');
|
||||
transferSpacing(div, node, 'margin', '');
|
||||
transferSpacing(div, node, 'padding', '');
|
||||
transferSpacing(div, node, 'border', 'Width');
|
||||
transfer(div, node, 'flexDirection');
|
||||
transfer(div, node, 'direction');
|
||||
transferFlex(div, node);
|
||||
transfer(div, node, 'flexWrap');
|
||||
transfer(div, node, 'justifyContent');
|
||||
transfer(div, node, 'alignSelf');
|
||||
transfer(div, node, 'alignItems');
|
||||
transfer(div, node, 'alignContent');
|
||||
transfer(div, node, 'position');
|
||||
transfer(div, node, 'overflow');
|
||||
parent.appendChild(div);
|
||||
(node.children || []).forEach(function(child) {
|
||||
renderNode(div, child);
|
||||
});
|
||||
if (node.style.measure) {
|
||||
div.innerText = node.style.measure.toString();
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
var div = renderNode(body, node);
|
||||
|
||||
function buildLayout(absoluteRect, div) {
|
||||
var rect = div.getBoundingClientRect();
|
||||
var result = {
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
top: rect.top - absoluteRect.top,
|
||||
left: rect.left - absoluteRect.left
|
||||
};
|
||||
|
||||
var children = [];
|
||||
for (var child = div.firstChild; child; child = child.nextSibling) {
|
||||
if (child.nodeType !== 3 /* textNode */) {
|
||||
children.push(buildLayout(rect, child));
|
||||
}
|
||||
}
|
||||
if (children.length) {
|
||||
result.children = children;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
var layout = buildLayout({left: 0, top: 0}, div);
|
||||
body.removeChild(div);
|
||||
return layout;
|
||||
}
|
||||
|
||||
function inplaceRoundNumbersInObject(obj) {
|
||||
if (!testMeasurePrecision) {
|
||||
// undefined/0, disables rounding
|
||||
return;
|
||||
}
|
||||
|
||||
for (var key in obj) {
|
||||
if (!obj.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var val = obj[key];
|
||||
if (typeof val === 'number') {
|
||||
obj[key] = Math.floor((val * testMeasurePrecision) + 0.5) / testMeasurePrecision;
|
||||
} else if (typeof val === 'object') {
|
||||
inplaceRoundNumbersInObject(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nameLayout(name, layout) {
|
||||
var namedLayout = {name: name};
|
||||
for (var key in layout) {
|
||||
namedLayout[key] = layout[key];
|
||||
}
|
||||
return namedLayout;
|
||||
}
|
||||
|
||||
function testFillNodes(node, filledNode) {
|
||||
expect(fillNodes(node)).toEqual(filledNode);
|
||||
}
|
||||
|
||||
function testExtractNodes(node, extractedNode) {
|
||||
expect(extractNodes(node)).toEqual(extractedNode);
|
||||
}
|
||||
|
||||
function testCanUseCachedMeasurement(canReuse, spec, cacheEntry) {
|
||||
var availableWidth = spec.availableWidth;
|
||||
var availableHeight = spec.availableHeight;
|
||||
var widthMeasureMode = spec.widthMeasureMode;
|
||||
var heightMeasureMode = spec.heightMeasureMode;
|
||||
|
||||
expect(
|
||||
canUseCachedMeasurement(
|
||||
availableWidth, availableHeight,
|
||||
0, 0,
|
||||
widthMeasureMode, heightMeasureMode,
|
||||
cacheEntry
|
||||
)
|
||||
).toEqual(canReuse);
|
||||
}
|
||||
|
||||
function testNamedLayout(name, layoutA, layoutB) {
|
||||
expect(nameLayout(name, layoutA))
|
||||
.toEqual(nameLayout(name, layoutB));
|
||||
}
|
||||
|
||||
function isEqual(a, b) {
|
||||
// computeCSSLayout and computeDOMLayout output a tree with same ordered elements
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
}
|
||||
|
||||
function reduceTest(node) {
|
||||
function isWorking() {
|
||||
return isEqual(
|
||||
computeDOMLayout(node),
|
||||
computeCSSLayout(node)
|
||||
);
|
||||
}
|
||||
if (isWorking()) {
|
||||
return node;
|
||||
}
|
||||
|
||||
var isModified = true;
|
||||
|
||||
function rec(node) {
|
||||
var key;
|
||||
var value;
|
||||
|
||||
// Style
|
||||
for (key in node.style) {
|
||||
value = node.style[key];
|
||||
delete node.style[key];
|
||||
if (isWorking()) {
|
||||
node.style[key] = value;
|
||||
} else {
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
// Round values
|
||||
for (key in node.style) {
|
||||
value = node.style[key];
|
||||
if (value > 100) {
|
||||
node.style[key] = Math.round(value / 100) * 100;
|
||||
} else if (value > 10) {
|
||||
node.style[key] = Math.round(value / 10) * 10;
|
||||
} else if (value > 1) {
|
||||
node.style[key] = 5;
|
||||
}
|
||||
if (node.style[key] !== value) {
|
||||
if (isWorking()) {
|
||||
node.style[key] = value;
|
||||
} else {
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Children
|
||||
for (var i = 0; node.children && i < node.children.length; ++i) {
|
||||
value = node.children[i];
|
||||
node.children.splice(i, 1);
|
||||
if (isWorking()) {
|
||||
if (!node.children) {
|
||||
node.children = [];
|
||||
}
|
||||
node.children.splice(i, 0, value);
|
||||
rec(node.children[i]);
|
||||
} else {
|
||||
i--;
|
||||
isModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (isModified) {
|
||||
isModified = false;
|
||||
rec(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
var iframeText;
|
||||
function measureTextSizes(text, width) {
|
||||
iframeText = iframeText || document.createElement('iframe');
|
||||
document.body.appendChild(iframeText);
|
||||
|
||||
var body = iframeText.contentDocument.body;
|
||||
if (width === undefined || isNaN(width)) {
|
||||
width = Infinity;
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.style.width = (width === Infinity ? 10000000 : width) + 'px';
|
||||
div.style.display = 'flex';
|
||||
div.style.flexDirection = 'column';
|
||||
div.style.alignItems = 'flex-start';
|
||||
div.style.alignContent = 'flex-start';
|
||||
|
||||
var span = document.createElement('span');
|
||||
span.style.display = 'flex';
|
||||
span.style.flexDirection = 'column';
|
||||
span.style.alignItems = 'flex-start';
|
||||
span.style.alignContent = 'flex-start';
|
||||
span.innerText = text;
|
||||
|
||||
div.appendChild(span);
|
||||
body.appendChild(div);
|
||||
var rect = span.getBoundingClientRect();
|
||||
body.removeChild(div);
|
||||
return {
|
||||
width: rect.width,
|
||||
height: rect.height
|
||||
};
|
||||
}
|
||||
|
||||
var texts = {
|
||||
small: 'small',
|
||||
big: 'loooooooooong with space'
|
||||
};
|
||||
|
||||
var preDefinedTextSizes = {
|
||||
smallWidth: 34.671875,
|
||||
smallHeight: 18,
|
||||
bigWidth: 172.421875,
|
||||
bigHeight: 36,
|
||||
bigMinWidth: 100.4375
|
||||
};
|
||||
|
||||
// Note(prenaux): Clearly not what I would like, but it seems to be the only
|
||||
// way :( My guess is that since the font on Windows is
|
||||
// different than on OSX it has a different size.
|
||||
if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('Windows NT') > -1) {
|
||||
preDefinedTextSizes.bigHeight = 36;
|
||||
}
|
||||
|
||||
var textSizes;
|
||||
if (typeof require === 'function') {
|
||||
textSizes = preDefinedTextSizes;
|
||||
} else {
|
||||
textSizes = {
|
||||
smallWidth: measureTextSizes(texts.small, 0).width,
|
||||
smallHeight: measureTextSizes(texts.small, 0).height,
|
||||
bigWidth: measureTextSizes(texts.big).width,
|
||||
bigHeight: measureTextSizes(texts.big, 0).height,
|
||||
bigMinWidth: measureTextSizes(texts.big, 0).width
|
||||
};
|
||||
}
|
||||
|
||||
// round the text sizes so that we dont have to update it for every browser
|
||||
// update, assumes we're ok with pixel precision
|
||||
inplaceRoundNumbersInObject(preDefinedTextSizes);
|
||||
inplaceRoundNumbersInObject(textSizes);
|
||||
|
||||
return {
|
||||
texts: texts,
|
||||
textSizes: textSizes,
|
||||
preDefinedTextSizes: preDefinedTextSizes,
|
||||
testLayout: function(node, expectedLayout) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
inplaceRoundNumbersInObject(expectedLayout);
|
||||
testNamedLayout('expected-dom', expectedLayout, domLayout);
|
||||
testNamedLayout('layout-dom', layout, domLayout);
|
||||
},
|
||||
testLayoutAgainstDomOnly: function(node) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
testNamedLayout('layout-dom', layout, domLayout);
|
||||
},
|
||||
testLayoutAgainstExpectedOnly: function(node, expectedLayout) {
|
||||
var layout = computeCSSLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(expectedLayout);
|
||||
testNamedLayout('expected-dom', expectedLayout, layout);
|
||||
},
|
||||
testFillNodes: testFillNodes,
|
||||
testExtractNodes: testExtractNodes,
|
||||
testCanUseCachedMeasurement: testCanUseCachedMeasurement,
|
||||
testRandomLayout: function(node) {
|
||||
var layout = computeCSSLayout(node);
|
||||
var domLayout = computeDOMLayout(node);
|
||||
inplaceRoundNumbersInObject(layout);
|
||||
inplaceRoundNumbersInObject(domLayout);
|
||||
expect({node: node, layout: layout})
|
||||
.toEqual({node: node, layout: domLayout});
|
||||
},
|
||||
testsFinished: function() {
|
||||
console.log('tests finished!');
|
||||
},
|
||||
computeLayout: computeCSSLayout,
|
||||
computeDOMLayout: computeDOMLayout,
|
||||
reduceTest: reduceTest,
|
||||
text: function(text) {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode === 'undefined') {
|
||||
width = Infinity;
|
||||
}
|
||||
|
||||
// Constants for testing purposes between C/JS and other platforms
|
||||
// Comment this block of code if you want to use the browser to
|
||||
// generate proper sizes
|
||||
if (text === texts.small) {
|
||||
return {
|
||||
width: Math.min(textSizes.smallWidth, width),
|
||||
height: textSizes.smallHeight
|
||||
};
|
||||
}
|
||||
if (text === texts.big) {
|
||||
var res = {
|
||||
width: width >= textSizes.bigWidth ? textSizes.bigWidth : Math.max(textSizes.bigMinWidth, width),
|
||||
height: width >= textSizes.bigWidth ? textSizes.smallHeight : textSizes.bigHeight
|
||||
};
|
||||
return res;
|
||||
}
|
||||
};
|
||||
// Name of the function is used in DOM tests as a text in the measured node
|
||||
// and as a way to tell different measure functions apart in transpiled tests
|
||||
fn.toString = function() { return text; };
|
||||
return fn;
|
||||
},
|
||||
measureWithRatio2: function() {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode !== 'undefined') {
|
||||
height = width * 2;
|
||||
} else if (heightMode !== 'undefined') {
|
||||
width = height * 2;
|
||||
} else {
|
||||
// This should be Infinity, but it would be pain to transpile,
|
||||
// so let's just go with big numbers.
|
||||
height = 99999;
|
||||
width = 99999;
|
||||
}
|
||||
return {width: width, height: height};
|
||||
};
|
||||
// This is necessary for transpiled tests, see previous comment
|
||||
fn.toString = function() { return 'measureWithRatio2'; };
|
||||
return fn;
|
||||
},
|
||||
measureWithMatchParent: function() {
|
||||
var fn = function(width, widthMode, height, heightMode) {
|
||||
if (widthMode === 'undefined') {
|
||||
width = 99999;
|
||||
}
|
||||
if (heightMode === 'undefined') {
|
||||
height = 99999;
|
||||
}
|
||||
return {width: width, height: height};
|
||||
};
|
||||
// This is necessary for transpiled tests, see previous comment
|
||||
fn.toString = function() { return 'measureWithMatchParent'; };
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = layoutTestUtils;
|
||||
}
|
1817
java/Layout.c
1817
java/Layout.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
200
java/Layout.h
200
java/Layout.h
|
@ -1,200 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LAYOUT_H
|
||||
#define __LAYOUT_H
|
||||
|
||||
#include <math.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
// Not defined in MSVC++
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *)__nan)
|
||||
#endif
|
||||
|
||||
#define CSS_UNDEFINED NAN
|
||||
|
||||
typedef enum {
|
||||
CSS_DIRECTION_INHERIT = 0,
|
||||
CSS_DIRECTION_LTR,
|
||||
CSS_DIRECTION_RTL
|
||||
} css_direction_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_FLEX_DIRECTION_COLUMN = 0,
|
||||
CSS_FLEX_DIRECTION_COLUMN_REVERSE,
|
||||
CSS_FLEX_DIRECTION_ROW,
|
||||
CSS_FLEX_DIRECTION_ROW_REVERSE
|
||||
} css_flex_direction_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_JUSTIFY_FLEX_START = 0,
|
||||
CSS_JUSTIFY_CENTER,
|
||||
CSS_JUSTIFY_FLEX_END,
|
||||
CSS_JUSTIFY_SPACE_BETWEEN,
|
||||
CSS_JUSTIFY_SPACE_AROUND
|
||||
} css_justify_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_OVERFLOW_VISIBLE = 0,
|
||||
CSS_OVERFLOW_HIDDEN
|
||||
} css_overflow_t;
|
||||
|
||||
// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
|
||||
// alignItems.
|
||||
typedef enum {
|
||||
CSS_ALIGN_AUTO = 0,
|
||||
CSS_ALIGN_FLEX_START,
|
||||
CSS_ALIGN_CENTER,
|
||||
CSS_ALIGN_FLEX_END,
|
||||
CSS_ALIGN_STRETCH
|
||||
} css_align_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_POSITION_RELATIVE = 0,
|
||||
CSS_POSITION_ABSOLUTE
|
||||
} css_position_type_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_NOWRAP = 0,
|
||||
CSS_WRAP
|
||||
} css_wrap_type_t;
|
||||
|
||||
// Note: left and top are shared between position[2] and position[4], so
|
||||
// they have to be before right and bottom.
|
||||
typedef enum {
|
||||
CSS_LEFT = 0,
|
||||
CSS_TOP,
|
||||
CSS_RIGHT,
|
||||
CSS_BOTTOM,
|
||||
CSS_START,
|
||||
CSS_END,
|
||||
CSS_POSITION_COUNT
|
||||
} css_position_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_MEASURE_MODE_UNDEFINED = 0,
|
||||
CSS_MEASURE_MODE_EXACTLY,
|
||||
CSS_MEASURE_MODE_AT_MOST,
|
||||
CSS_MEASURE_MODE_COUNT
|
||||
} css_measure_mode_t;
|
||||
|
||||
typedef enum {
|
||||
CSS_WIDTH = 0,
|
||||
CSS_HEIGHT
|
||||
} css_dimension_t;
|
||||
|
||||
typedef struct {
|
||||
float available_width;
|
||||
float available_height;
|
||||
css_measure_mode_t width_measure_mode;
|
||||
css_measure_mode_t height_measure_mode;
|
||||
|
||||
float computed_width;
|
||||
float computed_height;
|
||||
} css_cached_measurement_t;
|
||||
|
||||
enum {
|
||||
// This value was chosen based on empiracle data. Even the most complicated
|
||||
// layouts should not require more than 16 entries to fit within the cache.
|
||||
CSS_MAX_CACHED_RESULT_COUNT = 16
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
float position[4];
|
||||
float dimensions[2];
|
||||
css_direction_t direction;
|
||||
|
||||
float flex_basis;
|
||||
|
||||
// Instead of recomputing the entire layout every single time, we
|
||||
// cache some information to break early when nothing changed
|
||||
bool should_update;
|
||||
int generation_count;
|
||||
css_direction_t last_parent_direction;
|
||||
|
||||
int next_cached_measurements_index;
|
||||
css_cached_measurement_t cached_measurements[CSS_MAX_CACHED_RESULT_COUNT];
|
||||
float measured_dimensions[2];
|
||||
|
||||
css_cached_measurement_t cached_layout;
|
||||
} css_layout_t;
|
||||
|
||||
typedef struct {
|
||||
float dimensions[2];
|
||||
} css_dim_t;
|
||||
|
||||
typedef struct {
|
||||
css_direction_t direction;
|
||||
css_flex_direction_t flex_direction;
|
||||
css_justify_t justify_content;
|
||||
css_align_t align_content;
|
||||
css_align_t align_items;
|
||||
css_align_t align_self;
|
||||
css_position_type_t position_type;
|
||||
css_wrap_type_t flex_wrap;
|
||||
css_overflow_t overflow;
|
||||
float flex;
|
||||
float margin[6];
|
||||
float position[4];
|
||||
/**
|
||||
* You should skip all the rules that contain negative values for the
|
||||
* following attributes. For example:
|
||||
* {padding: 10, paddingLeft: -5}
|
||||
* should output:
|
||||
* {left: 10 ...}
|
||||
* the following two are incorrect:
|
||||
* {left: -5 ...}
|
||||
* {left: 0 ...}
|
||||
*/
|
||||
float padding[6];
|
||||
float border[6];
|
||||
float dimensions[2];
|
||||
float minDimensions[2];
|
||||
float maxDimensions[2];
|
||||
} css_style_t;
|
||||
|
||||
typedef struct css_node css_node_t;
|
||||
struct css_node {
|
||||
css_style_t style;
|
||||
css_layout_t layout;
|
||||
int children_count;
|
||||
int line_index;
|
||||
|
||||
css_node_t* next_child;
|
||||
|
||||
css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
|
||||
void (*print)(void *context);
|
||||
struct css_node* (*get_child)(void *context, int i);
|
||||
bool (*is_dirty)(void *context);
|
||||
bool (*is_text_node)(void *context);
|
||||
void *context;
|
||||
};
|
||||
|
||||
// Lifecycle of nodes and children
|
||||
css_node_t *new_css_node(void);
|
||||
void init_css_node(css_node_t *node);
|
||||
void free_css_node(css_node_t *node);
|
||||
|
||||
// Print utilities
|
||||
typedef enum {
|
||||
CSS_PRINT_LAYOUT = 1,
|
||||
CSS_PRINT_STYLE = 2,
|
||||
CSS_PRINT_CHILDREN = 4,
|
||||
} css_print_options_t;
|
||||
void print_css_node(css_node_t *node, css_print_options_t options);
|
||||
|
||||
// Function that computes the layout!
|
||||
void layoutNode(css_node_t *node, float availableWidth, float availableHeight, css_direction_t parentDirection);
|
||||
bool isUndefined(float value);
|
||||
|
||||
#endif
|
1708
java/Layout.js
1708
java/Layout.js
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSAlign {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public class CSSCachedMeasurement {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public class CSSConstants {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSDirection {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSFlexDirection {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSJustify {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
import java.util.Arrays;
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
/**
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSMeasureMode {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
import javax.annotation.Nullable;
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSOverflow {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSPositionType {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
import java.util.Arrays;
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public enum CSSWrap {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
/**
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
public class FloatUtil {
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
|
@ -551,47 +552,46 @@ public class LayoutEngine {
|
|||
CSSMeasureMode widthMeasureMode,
|
||||
CSSMeasureMode heightMeasureMode,
|
||||
boolean performLayout) {
|
||||
/** START_GENERATED **/
|
||||
|
||||
|
||||
Assertions.assertCondition(Float.isNaN(availableWidth) ? widthMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableWidth is indefinite so widthMeasureMode must be CSSMeasureMode.UNDEFINED");
|
||||
Assertions.assertCondition(Float.isNaN(availableHeight) ? heightMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableHeight is indefinite so heightMeasureMode must be CSSMeasureMode.UNDEFINED");
|
||||
|
||||
|
||||
float paddingAndBorderAxisRow = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW])));
|
||||
float paddingAndBorderAxisColumn = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
|
||||
float marginAxisRow = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
float marginAxisColumn = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
|
||||
|
||||
// Set the resolved resolution in the node's layout.
|
||||
CSSDirection direction = resolveDirection(node, parentDirection);
|
||||
node.layout.direction = direction;
|
||||
|
||||
|
||||
// For content (text) nodes, determine the dimensions based on the text contents.
|
||||
if (isMeasureDefined(node)) {
|
||||
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
||||
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
||||
|
||||
|
||||
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
|
||||
|
||||
|
||||
// Don't bother sizing the text if both dimensions are already defined.
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);
|
||||
} else if (innerWidth <= 0 || innerHeight <= 0) {
|
||||
|
||||
|
||||
// Don't bother sizing the text if there's no horizontal or vertical space.
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
} else {
|
||||
|
||||
|
||||
// Measure the text under the current constraints.
|
||||
MeasureOutput measureDim = node.measure(
|
||||
|
||||
|
||||
layoutContext.measureOutput,
|
||||
innerWidth,
|
||||
widthMeasureMode,
|
||||
innerHeight,
|
||||
heightMeasureMode
|
||||
);
|
||||
|
||||
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW,
|
||||
(widthMeasureMode == CSSMeasureMode.UNDEFINED || widthMeasureMode == CSSMeasureMode.AT_MOST) ?
|
||||
measureDim.width + paddingAndBorderAxisRow :
|
||||
|
@ -601,10 +601,10 @@ public class LayoutEngine {
|
|||
measureDim.height + paddingAndBorderAxisColumn :
|
||||
availableHeight - marginAxisColumn);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For nodes with no children, use the available values if they were provided, or
|
||||
// the minimum size as indicated by the padding and border sizes.
|
||||
int childCount = node.getChildCount();
|
||||
|
@ -619,7 +619,7 @@ public class LayoutEngine {
|
|||
availableHeight - marginAxisColumn);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If we're not being asked to perform a full layout, we can handle a number of common
|
||||
// cases here without incurring the cost of the remaining function.
|
||||
if (!performLayout) {
|
||||
|
@ -631,19 +631,19 @@ public class LayoutEngine {
|
|||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (widthMeasureMode == CSSMeasureMode.AT_MOST && availableWidth <= 0) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, Float.isNaN(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (heightMeasureMode == CSSMeasureMode.AT_MOST && availableHeight <= 0) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, Float.isNaN(availableWidth) ? 0 : (availableWidth - marginAxisRow));
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If we're being asked to use an exact width/height, there's no need to measure the children.
|
||||
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
|
@ -651,32 +651,32 @@ public class LayoutEngine {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM
|
||||
int mainAxis = resolveAxis(getFlexDirection(node), direction);
|
||||
int crossAxis = getCrossFlexDirection(mainAxis, direction);
|
||||
boolean isMainAxisRow = (mainAxis == CSS_FLEX_DIRECTION_ROW || mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE);
|
||||
CSSJustify justifyContent = node.style.justifyContent;
|
||||
boolean isNodeFlexWrap = (node.style.flexWrap == CSSWrap.WRAP);
|
||||
|
||||
|
||||
CSSNode firstAbsoluteChild = null;
|
||||
CSSNode currentAbsoluteChild = null;
|
||||
|
||||
|
||||
float leadingPaddingAndBorderMain = (node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]));
|
||||
float trailingPaddingAndBorderMain = (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
float leadingPaddingAndBorderCross = (node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]));
|
||||
float paddingAndBorderAxisMain = ((node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
|
||||
float paddingAndBorderAxisCross = ((node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (node.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + node.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
|
||||
|
||||
|
||||
CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
|
||||
CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
|
||||
|
||||
|
||||
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
||||
float availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
|
||||
float availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
|
||||
float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
||||
float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
||||
|
||||
|
||||
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
||||
CSSNode child;
|
||||
int i;
|
||||
|
@ -686,17 +686,17 @@ public class LayoutEngine {
|
|||
CSSMeasureMode childHeightMeasureMode;
|
||||
for (i = 0; i < childCount; i++) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (performLayout) {
|
||||
// Set the initial position (relative to the parent).
|
||||
CSSDirection childDirection = resolveDirection(child, direction);
|
||||
setPosition(child, childDirection);
|
||||
}
|
||||
|
||||
|
||||
// Absolute-positioned children don't participate in flex layout. Add them
|
||||
// to a list that we can process later.
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE) {
|
||||
|
||||
|
||||
// Store a private linked list of absolutely positioned children
|
||||
// so that we can efficiently traverse them later.
|
||||
if (firstAbsoluteChild == null) {
|
||||
|
@ -708,27 +708,27 @@ public class LayoutEngine {
|
|||
currentAbsoluteChild = child;
|
||||
child.nextChild = null;
|
||||
} else {
|
||||
|
||||
|
||||
if (isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
|
||||
|
||||
// The width is definite, so use that as the flex basis.
|
||||
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_WIDTH], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]))));
|
||||
} else if (!isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
|
||||
|
||||
|
||||
// The height is definite, so use that as the flex basis.
|
||||
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]))));
|
||||
} else if (!isFlexBasisAuto(child) && !Float.isNaN(availableInnerMainDim)) {
|
||||
|
||||
|
||||
// If the basis isn't 'auto', it is assumed to be zero.
|
||||
child.layout.flexBasis = Math.max(0, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
} else {
|
||||
|
||||
|
||||
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
|
||||
childWidth = CSSConstants.UNDEFINED;
|
||||
childHeight = CSSConstants.UNDEFINED;
|
||||
childWidthMeasureMode = CSSMeasureMode.UNDEFINED;
|
||||
childHeightMeasureMode = CSSMeasureMode.UNDEFINED;
|
||||
|
||||
|
||||
if ((child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
childWidth = child.style.dimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
|
@ -737,7 +737,7 @@ public class LayoutEngine {
|
|||
childHeight = child.style.dimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
|
||||
|
||||
// According to the spec, if the main size is not definite and the
|
||||
// child's inline axis is parallel to the main axis (i.e. it's
|
||||
// horizontal), the child should be sized using "UNDEFINED" in
|
||||
|
@ -746,7 +746,7 @@ public class LayoutEngine {
|
|||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
|
||||
// The W3C spec doesn't say anything about the 'overflow' property,
|
||||
// but all major browsers appear to implement the following logic.
|
||||
if (node.style.overflow == CSSOverflow.HIDDEN) {
|
||||
|
@ -755,7 +755,7 @@ public class LayoutEngine {
|
|||
childHeightMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If child has no defined size in the cross axis and is set to stretch, set the cross
|
||||
// axis to be measured exactly with the available inner width
|
||||
if (!isMainAxisRow &&
|
||||
|
@ -774,76 +774,76 @@ public class LayoutEngine {
|
|||
childHeight = availableInnerHeight;
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
|
||||
|
||||
// Measure the child
|
||||
layoutNodeInternal(layoutContext, child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
|
||||
|
||||
|
||||
child.layout.flexBasis = Math.max(isMainAxisRow ? child.layout.measuredDimensions[DIMENSION_WIDTH] : child.layout.measuredDimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
|
||||
|
||||
|
||||
// Indexes of children that represent the first and last items in the line.
|
||||
int startOfLineIndex = 0;
|
||||
int endOfLineIndex = 0;
|
||||
|
||||
|
||||
// Number of lines.
|
||||
int lineCount = 0;
|
||||
|
||||
|
||||
// Accumulated cross dimensions of all lines so far.
|
||||
float totalLineCrossDim = 0;
|
||||
|
||||
|
||||
// Max main dimension of all the lines.
|
||||
float maxLineMainDim = 0;
|
||||
|
||||
|
||||
while (endOfLineIndex < childCount) {
|
||||
|
||||
|
||||
// Number of items on the currently line. May be different than the difference
|
||||
// between start and end indicates because we skip over absolute-positioned items.
|
||||
int itemsOnLine = 0;
|
||||
|
||||
|
||||
// sizeConsumedOnCurrentLine is accumulation of the dimensions and margin
|
||||
// of all the children on the current line. This will be used in order to
|
||||
// either set the dimensions of the node if none already exist or to compute
|
||||
// the remaining space left for the flexible children.
|
||||
float sizeConsumedOnCurrentLine = 0;
|
||||
|
||||
|
||||
float totalFlexGrowFactors = 0;
|
||||
float totalFlexShrinkScaledFactors = 0;
|
||||
|
||||
|
||||
i = startOfLineIndex;
|
||||
|
||||
|
||||
// Maintain a linked list of the child nodes that can shrink and/or grow.
|
||||
CSSNode firstRelativeChild = null;
|
||||
CSSNode currentRelativeChild = null;
|
||||
|
||||
|
||||
// Add items to the current line until it's full or we run out of items.
|
||||
while (i < childCount) {
|
||||
child = node.getChildAt(i);
|
||||
child.lineIndex = lineCount;
|
||||
|
||||
|
||||
if (child.style.positionType != CSSPositionType.ABSOLUTE) {
|
||||
float outerFlexBasis = child.layout.flexBasis + (child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
|
||||
|
||||
// If this is a multi-line flow and this item pushes us over the available size, we've
|
||||
// hit the end of the current line. Break out of the loop and lay out the current line.
|
||||
if (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sizeConsumedOnCurrentLine += outerFlexBasis;
|
||||
itemsOnLine++;
|
||||
|
||||
|
||||
if ((child.style.positionType == CSSPositionType.RELATIVE && child.style.flex != 0)) {
|
||||
totalFlexGrowFactors += getFlexGrowFactor(child);
|
||||
|
||||
|
||||
// Unlike the grow factor, the shrink factor is scaled relative to the child
|
||||
// dimension.
|
||||
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
|
||||
}
|
||||
|
||||
|
||||
// Store a private linked list of children that need to be layed out.
|
||||
if (firstRelativeChild == null) {
|
||||
firstRelativeChild = child;
|
||||
|
@ -854,20 +854,20 @@ public class LayoutEngine {
|
|||
currentRelativeChild = child;
|
||||
child.nextChild = null;
|
||||
}
|
||||
|
||||
|
||||
i++;
|
||||
endOfLineIndex++;
|
||||
}
|
||||
|
||||
|
||||
// If we don't need to measure the cross axis, we can skip the entire flex step.
|
||||
boolean canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
// In order to position the elements in the main axis, we have two
|
||||
// controls. The space between the beginning and the first element
|
||||
// and the space between each two elements.
|
||||
float leadingMainDim = 0;
|
||||
float betweenMainDim = 0;
|
||||
|
||||
|
||||
// STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS
|
||||
// Calculate the remaining available space that needs to be allocated.
|
||||
// If the main dimension size isn't known, it is computed based on
|
||||
|
@ -881,17 +881,17 @@ public class LayoutEngine {
|
|||
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
|
||||
remainingFreeSpace = -sizeConsumedOnCurrentLine;
|
||||
}
|
||||
|
||||
|
||||
float originalRemainingFreeSpace = remainingFreeSpace;
|
||||
float deltaFreeSpace = 0;
|
||||
|
||||
|
||||
if (!canSkipFlex) {
|
||||
float childFlexBasis;
|
||||
float flexShrinkScaledFactor;
|
||||
float flexGrowFactor;
|
||||
float baseMainSize;
|
||||
float boundMainSize;
|
||||
|
||||
|
||||
// Do two passes over the flex items to figure out how to distribute the remaining space.
|
||||
// The first pass finds the items whose min/max constraints trigger, freezes them at those
|
||||
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
|
||||
|
@ -904,17 +904,17 @@ public class LayoutEngine {
|
|||
// that needs to be repeated a variable number of times. The algorithm implemented here
|
||||
// won't handle all cases but it was simpler to implement and it mitigates performance
|
||||
// concerns because we know exactly how many passes it'll do.
|
||||
|
||||
|
||||
// First pass: detect the flex items whose min/max constraints trigger
|
||||
float deltaFlexShrinkScaledFactors = 0;
|
||||
float deltaFlexGrowFactors = 0;
|
||||
currentRelativeChild = firstRelativeChild;
|
||||
while (currentRelativeChild != null) {
|
||||
childFlexBasis = currentRelativeChild.layout.flexBasis;
|
||||
|
||||
|
||||
if (remainingFreeSpace < 0) {
|
||||
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
|
||||
|
||||
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
|
@ -930,7 +930,7 @@ public class LayoutEngine {
|
|||
}
|
||||
} else if (remainingFreeSpace > 0) {
|
||||
flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
|
||||
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
|
@ -945,24 +945,24 @@ public class LayoutEngine {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentRelativeChild = currentRelativeChild.nextChild;
|
||||
}
|
||||
|
||||
|
||||
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
|
||||
totalFlexGrowFactors += deltaFlexGrowFactors;
|
||||
remainingFreeSpace += deltaFreeSpace;
|
||||
|
||||
|
||||
// Second pass: resolve the sizes of the flexible items
|
||||
deltaFreeSpace = 0;
|
||||
currentRelativeChild = firstRelativeChild;
|
||||
while (currentRelativeChild != null) {
|
||||
childFlexBasis = currentRelativeChild.layout.flexBasis;
|
||||
float updatedMainSize = childFlexBasis;
|
||||
|
||||
|
||||
if (remainingFreeSpace < 0) {
|
||||
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
|
||||
|
||||
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
|
||||
|
@ -970,20 +970,20 @@ public class LayoutEngine {
|
|||
}
|
||||
} else if (remainingFreeSpace > 0) {
|
||||
flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
|
||||
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
|
||||
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
deltaFreeSpace -= updatedMainSize - childFlexBasis;
|
||||
|
||||
|
||||
if (isMainAxisRow) {
|
||||
childWidth = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
if (!Float.isNaN(availableInnerCrossDim) &&
|
||||
!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0) &&
|
||||
heightMeasureMode == CSSMeasureMode.EXACTLY &&
|
||||
|
@ -1000,7 +1000,7 @@ public class LayoutEngine {
|
|||
} else {
|
||||
childHeight = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
if (!Float.isNaN(availableInnerCrossDim) &&
|
||||
!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0) &&
|
||||
widthMeasureMode == CSSMeasureMode.EXACTLY &&
|
||||
|
@ -1015,32 +1015,32 @@ public class LayoutEngine {
|
|||
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean requiresStretchLayout = !(currentRelativeChild.style.dimensions[dim[crossAxis]] >= 0.0) &&
|
||||
getAlignItem(node, currentRelativeChild) == CSSAlign.STRETCH;
|
||||
|
||||
|
||||
// Recursively call the layout algorithm for this child with the updated main size.
|
||||
layoutNodeInternal(layoutContext, currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, "flex");
|
||||
|
||||
|
||||
currentRelativeChild = currentRelativeChild.nextChild;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
|
||||
|
||||
|
||||
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
|
||||
|
||||
|
||||
// At this point, all the children have their dimensions set in the main axis.
|
||||
// Their dimensions are also set in the cross axis with the exception of items
|
||||
// that are aligned "stretch". We need to compute these stretch values and
|
||||
// set the final positions.
|
||||
|
||||
|
||||
// If we are using "at most" rules in the main axis, we won't distribute
|
||||
// any remaining space at this point.
|
||||
if (measureModeMainDim == CSSMeasureMode.AT_MOST) {
|
||||
remainingFreeSpace = 0;
|
||||
}
|
||||
|
||||
|
||||
// Use justifyContent to figure out how to allocate the remaining space
|
||||
// available in the main axis.
|
||||
if (justifyContent != CSSJustify.FLEX_START) {
|
||||
|
@ -1061,13 +1061,13 @@ public class LayoutEngine {
|
|||
leadingMainDim = betweenMainDim / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float mainDim = leadingPaddingAndBorderMain + leadingMainDim;
|
||||
float crossDim = 0;
|
||||
|
||||
|
||||
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE &&
|
||||
!Float.isNaN(child.style.position[leading[mainAxis]])) {
|
||||
if (performLayout) {
|
||||
|
@ -1084,7 +1084,7 @@ public class LayoutEngine {
|
|||
// we put it at the current accumulated offset.
|
||||
child.layout.position[pos[mainAxis]] += mainDim;
|
||||
}
|
||||
|
||||
|
||||
// Now that we placed the element, we need to update the variables.
|
||||
// We need to do that only for relative elements. Absolute elements
|
||||
// do not take part in that phase.
|
||||
|
@ -1098,7 +1098,7 @@ public class LayoutEngine {
|
|||
// The main dimension is the sum of all the elements dimension plus
|
||||
// the spacing.
|
||||
mainDim += betweenMainDim + (child.layout.measuredDimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
|
||||
|
||||
|
||||
// The cross dimension is the max of the elements dimension since there
|
||||
// can only be one element in that cross dimension.
|
||||
crossDim = Math.max(crossDim, (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
|
||||
|
@ -1106,33 +1106,33 @@ public class LayoutEngine {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mainDim += trailingPaddingAndBorderMain;
|
||||
|
||||
|
||||
float containerCrossAxis = availableInnerCrossDim;
|
||||
if (measureModeCrossDim == CSSMeasureMode.UNDEFINED || measureModeCrossDim == CSSMeasureMode.AT_MOST) {
|
||||
// Compute the cross axis from the max cross dimension of the children.
|
||||
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
|
||||
|
||||
|
||||
if (measureModeCrossDim == CSSMeasureMode.AT_MOST) {
|
||||
containerCrossAxis = Math.min(containerCrossAxis, availableInnerCrossDim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If there's no flex wrap, the cross dimension is defined by the container.
|
||||
if (!isNodeFlexWrap && measureModeCrossDim == CSSMeasureMode.EXACTLY) {
|
||||
crossDim = availableInnerCrossDim;
|
||||
}
|
||||
|
||||
|
||||
// Clamp to the min/max size specified on the container.
|
||||
crossDim = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
|
||||
|
||||
|
||||
// STEP 7: CROSS-AXIS ALIGNMENT
|
||||
// We can skip child alignment if we're just measuring the container.
|
||||
if (performLayout) {
|
||||
for (i = startOfLineIndex; i < endOfLineIndex; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (child.style.positionType == CSSPositionType.ABSOLUTE) {
|
||||
// If the child is absolutely positioned and has a top/left/bottom/right
|
||||
// set, override all the previously computed positions to set it correctly.
|
||||
|
@ -1146,18 +1146,18 @@ public class LayoutEngine {
|
|||
}
|
||||
} else {
|
||||
float leadingCrossDim = leadingPaddingAndBorderCross;
|
||||
|
||||
|
||||
// For a relative children, we're either using alignItems (parent) or
|
||||
// alignSelf (child) in order to determine the position in the cross axis
|
||||
CSSAlign alignItem = getAlignItem(node, child);
|
||||
|
||||
|
||||
// If the child uses align stretch, we need to lay it out one more time, this time
|
||||
// forcing the cross-axis size to be the computed cross size for the current line.
|
||||
if (alignItem == CSSAlign.STRETCH) {
|
||||
childWidth = child.layout.measuredDimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childHeight = child.layout.measuredDimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
boolean isCrossSizeDefinite = false;
|
||||
|
||||
|
||||
if (isMainAxisRow) {
|
||||
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0);
|
||||
childHeight = crossDim;
|
||||
|
@ -1165,7 +1165,7 @@ public class LayoutEngine {
|
|||
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0);
|
||||
childWidth = crossDim;
|
||||
}
|
||||
|
||||
|
||||
// If the child defines a definite size for its cross axis, there's no need to stretch.
|
||||
if (!isCrossSizeDefinite) {
|
||||
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
|
@ -1174,36 +1174,36 @@ public class LayoutEngine {
|
|||
}
|
||||
} else if (alignItem != CSSAlign.FLEX_START) {
|
||||
float remainingCrossDim = containerCrossAxis - (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]));
|
||||
|
||||
|
||||
if (alignItem == CSSAlign.CENTER) {
|
||||
leadingCrossDim += remainingCrossDim / 2;
|
||||
} else { // CSSAlign.FLEX_END
|
||||
leadingCrossDim += remainingCrossDim;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// And we apply the position
|
||||
child.layout.position[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
totalLineCrossDim += crossDim;
|
||||
maxLineMainDim = Math.max(maxLineMainDim, mainDim);
|
||||
|
||||
|
||||
// Reset variables for new line.
|
||||
lineCount++;
|
||||
startOfLineIndex = endOfLineIndex;
|
||||
endOfLineIndex = startOfLineIndex;
|
||||
}
|
||||
|
||||
|
||||
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
||||
if (lineCount > 1 && performLayout && !Float.isNaN(availableInnerCrossDim)) {
|
||||
float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;
|
||||
|
||||
|
||||
float crossDimLead = 0;
|
||||
float currentLead = leadingPaddingAndBorderCross;
|
||||
|
||||
|
||||
CSSAlign alignContent = node.style.alignContent;
|
||||
if (alignContent == CSSAlign.FLEX_END) {
|
||||
currentLead += remainingAlignContentDim;
|
||||
|
@ -1214,12 +1214,12 @@ public class LayoutEngine {
|
|||
crossDimLead = (remainingAlignContentDim / lineCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int endIndex = 0;
|
||||
for (i = 0; i < lineCount; ++i) {
|
||||
int startIndex = endIndex;
|
||||
int j;
|
||||
|
||||
|
||||
// compute the line's height and find the endIndex
|
||||
float lineHeight = 0;
|
||||
for (j = startIndex; j < childCount; ++j) {
|
||||
|
@ -1237,14 +1237,14 @@ public class LayoutEngine {
|
|||
}
|
||||
endIndex = j;
|
||||
lineHeight += crossDimLead;
|
||||
|
||||
|
||||
if (performLayout) {
|
||||
for (j = startIndex; j < endIndex; ++j) {
|
||||
child = node.getChildAt(j);
|
||||
if (child.style.positionType != CSSPositionType.RELATIVE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
CSSAlign alignContentAlignItem = getAlignItem(node, child);
|
||||
if (alignContentAlignItem == CSSAlign.FLEX_START) {
|
||||
child.layout.position[pos[crossAxis]] = currentLead + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]);
|
||||
|
@ -1260,15 +1260,15 @@ public class LayoutEngine {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentLead += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 9: COMPUTING FINAL DIMENSIONS
|
||||
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
|
||||
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);
|
||||
|
||||
|
||||
// If the user didn't specify a width or height for the node, set the
|
||||
// dimensions based on the children.
|
||||
if (measureModeMainDim == CSSMeasureMode.UNDEFINED) {
|
||||
|
@ -1281,7 +1281,7 @@ public class LayoutEngine {
|
|||
boundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)),
|
||||
paddingAndBorderAxisMain);
|
||||
}
|
||||
|
||||
|
||||
if (measureModeCrossDim == CSSMeasureMode.UNDEFINED) {
|
||||
// Clamp the size to the min/max size, if specified, and make sure it
|
||||
// doesn't go below the padding and border amount.
|
||||
|
@ -1292,48 +1292,48 @@ public class LayoutEngine {
|
|||
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
|
||||
paddingAndBorderAxisCross);
|
||||
}
|
||||
|
||||
|
||||
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
|
||||
if (performLayout) {
|
||||
boolean needsMainTrailingPos = false;
|
||||
boolean needsCrossTrailingPos = false;
|
||||
|
||||
|
||||
if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
|
||||
mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||
needsMainTrailingPos = true;
|
||||
}
|
||||
|
||||
|
||||
if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
|
||||
crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
|
||||
needsCrossTrailingPos = true;
|
||||
}
|
||||
|
||||
|
||||
// Set trailing position if necessary.
|
||||
if (needsMainTrailingPos || needsCrossTrailingPos) {
|
||||
for (i = 0; i < childCount; ++i) {
|
||||
child = node.getChildAt(i);
|
||||
|
||||
|
||||
if (needsMainTrailingPos) {
|
||||
child.layout.position[trailing[mainAxis]] = node.layout.measuredDimensions[dim[mainAxis]] - (child.style.positionType == CSSPositionType.ABSOLUTE ? 0 : child.layout.measuredDimensions[dim[mainAxis]]) - child.layout.position[pos[mainAxis]];
|
||||
}
|
||||
|
||||
|
||||
if (needsCrossTrailingPos) {
|
||||
child.layout.position[trailing[crossAxis]] = node.layout.measuredDimensions[dim[crossAxis]] - (child.style.positionType == CSSPositionType.ABSOLUTE ? 0 : child.layout.measuredDimensions[dim[crossAxis]]) - child.layout.position[pos[crossAxis]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
|
||||
currentAbsoluteChild = firstAbsoluteChild;
|
||||
while (currentAbsoluteChild != null) {
|
||||
// Now that we know the bounds of the container, perform layout again on the
|
||||
// absolutely-positioned children.
|
||||
if (performLayout) {
|
||||
|
||||
|
||||
childWidth = CSSConstants.UNDEFINED;
|
||||
childHeight = CSSConstants.UNDEFINED;
|
||||
|
||||
|
||||
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
|
||||
childWidth = currentAbsoluteChild.style.dimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
} else {
|
||||
|
@ -1345,7 +1345,7 @@ public class LayoutEngine {
|
|||
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
|
||||
childHeight = currentAbsoluteChild.style.dimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
} else {
|
||||
|
@ -1357,12 +1357,12 @@ public class LayoutEngine {
|
|||
childHeight = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN, childHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we're still missing one or the other dimension, measure the content.
|
||||
if (Float.isNaN(childWidth) || Float.isNaN(childHeight)) {
|
||||
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
childHeightMeasureMode = Float.isNaN(childHeight) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
|
||||
|
||||
|
||||
// According to the spec, if the main size is not definite and the
|
||||
// child's inline axis is parallel to the main axis (i.e. it's
|
||||
// horizontal), the child should be sized using "UNDEFINED" in
|
||||
|
@ -1371,7 +1371,7 @@ public class LayoutEngine {
|
|||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
|
||||
// The W3C spec doesn't say anything about the 'overflow' property,
|
||||
// but all major browsers appear to implement the following logic.
|
||||
if (node.style.overflow == CSSOverflow.HIDDEN) {
|
||||
|
@ -1380,14 +1380,14 @@ public class LayoutEngine {
|
|||
childHeightMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "abs-measure");
|
||||
childWidth = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
|
||||
childHeight = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
|
||||
}
|
||||
|
||||
|
||||
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, CSSMeasureMode.EXACTLY, CSSMeasureMode.EXACTLY, true, "abs-layout");
|
||||
|
||||
|
||||
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) &&
|
||||
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_ROW]])) {
|
||||
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
|
||||
|
@ -1395,7 +1395,7 @@ public class LayoutEngine {
|
|||
currentAbsoluteChild.layout.measuredDimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
|
||||
(Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]);
|
||||
}
|
||||
|
||||
|
||||
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) &&
|
||||
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_COLUMN]])) {
|
||||
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
|
||||
|
@ -1404,9 +1404,8 @@ public class LayoutEngine {
|
|||
(Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currentAbsoluteChild = currentAbsoluteChild.nextChild;
|
||||
}
|
||||
/** END_GENERATED **/
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
/**
|
|
@ -1,11 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) 2014, Facebook, Inc.
|
||||
* Copyright (c) 2014-present, 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.
|
||||
*/
|
||||
|
||||
package com.facebook.csslayout;
|
||||
|
||||
import javax.annotation.Nullable;
|
|
@ -1,13 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line=LF
|
||||
|
||||
[*.cs]
|
||||
indent_style=space
|
||||
indent_size=4
|
||||
|
||||
[*.js]
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
/.vs/
|
||||
*.user
|
||||
*.nupkg
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
/**
|
||||
* Tests for {@link CSSNode}.
|
||||
*/
|
||||
public class CSSNodeTest
|
||||
{
|
||||
|
||||
[Test]
|
||||
public void testAddChildGetParent()
|
||||
{
|
||||
CSSNode parent = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
Assert.IsNull(child.getParent());
|
||||
Assert.AreEqual(0, parent.getChildCount());
|
||||
|
||||
parent.addChildAt(child, 0);
|
||||
|
||||
Assert.AreEqual(1, parent.getChildCount());
|
||||
Assert.AreEqual(child, parent.getChildAt(0));
|
||||
Assert.AreEqual(parent, child.getParent());
|
||||
|
||||
parent.removeChildAt(0);
|
||||
|
||||
Assert.IsNull(child.getParent());
|
||||
Assert.AreEqual(0, parent.getChildCount());
|
||||
}
|
||||
|
||||
[Test, ExpectedException(typeof(InvalidOperationException))]
|
||||
public void testCannotAddChildToMultipleParents()
|
||||
{
|
||||
CSSNode parent1 = new CSSNode();
|
||||
CSSNode parent2 = new CSSNode();
|
||||
CSSNode child = new CSSNode();
|
||||
|
||||
parent1.addChildAt(child, 0);
|
||||
parent2.addChildAt(child, 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E687C8FD-0A0D-450F-853D-EC301BE1C038}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Facebook.CSSLayout.Tests</RootNamespace>
|
||||
<AssemblyName>Facebook.CSSLayout.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CSSNodeTest.cs" />
|
||||
<Compile Include="LayoutCachingTest.cs" />
|
||||
<Compile Include="LayoutEngineTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="TestConstants.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facebook.CSSLayout\Facebook.CSSLayout.csproj">
|
||||
<Project>{d534fb4b-a7d4-4a29-96d3-f39a91a259bd}</Project>
|
||||
<Name>Facebook.CSSLayout</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,240 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests for {@link LayoutEngine} and {@link CSSNode} to make sure layouts are only generated when
|
||||
* needed.
|
||||
*/
|
||||
public class LayoutCachingTest
|
||||
{
|
||||
|
||||
private void assertTreeHasNewLayout(bool expectedHasNewLayout, CSSNode root)
|
||||
{
|
||||
Assert.AreEqual(expectedHasNewLayout, root.HasNewLayout);
|
||||
|
||||
for (int i = 0; i < root.getChildCount(); i++)
|
||||
{
|
||||
assertTreeHasNewLayout(expectedHasNewLayout, root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
private void markLayoutAppliedForTree(CSSNode root)
|
||||
{
|
||||
root.MarkLayoutSeen();
|
||||
for (int i = 0; i < root.getChildCount(); i++)
|
||||
{
|
||||
markLayoutAppliedForTree(root.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testCachesFullTree()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
assertTreeHasNewLayout(true, root);
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.calculateLayout();
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenChildAdded()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c0c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
c0c1.Width = 200;
|
||||
c0c1.Height = 200;
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c0c0.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.addChildAt(c0c1, 1);
|
||||
|
||||
root.calculateLayout();
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenEnumPropertyChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.AlignSelf = CSSAlign.Center;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsFalse(c0c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesCacheWhenFloatPropertyChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.SetMargin(CSSSpacingType.Left, 10);
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesFullTreeWhenParentWidthChanges()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.Width = 200;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
Assert.IsTrue(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testDoesNotInvalidateCacheWhenPropertyIsTheSame()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
root.Width = 200;
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
root.Width = 200;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
assertTreeHasNewLayout(false, c0);
|
||||
assertTreeHasNewLayout(false, c1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidateCacheWhenHeightChangesPosition()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c1c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c1.addChildAt(c1c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c0.Height = 100;
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
Assert.IsFalse(c1c0.HasNewLayout);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void testInvalidatesOnNewMeasureFunction()
|
||||
{
|
||||
CSSNode root = new CSSNode();
|
||||
CSSNode c0 = new CSSNode();
|
||||
CSSNode c1 = new CSSNode();
|
||||
CSSNode c0c0 = new CSSNode();
|
||||
root.addChildAt(c0, 0);
|
||||
root.addChildAt(c1, 1);
|
||||
c0.addChildAt(c0c0, 0);
|
||||
|
||||
root.calculateLayout();
|
||||
markLayoutAppliedForTree(root);
|
||||
|
||||
c1.setMeasureFunction((node, width, widthMode, height, heightMode) => new MeasureOutput(100, 20));
|
||||
|
||||
root.calculateLayout();
|
||||
|
||||
Assert.IsTrue(root.HasNewLayout);
|
||||
Assert.IsTrue(c1.HasNewLayout);
|
||||
|
||||
Assert.IsTrue(c0.HasNewLayout);
|
||||
Assert.IsTrue(c0c0.HasNewLayout);
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("Facebook.CSSLayout.Tests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Facebook.CSSLayout.Tests")]
|
||||
[assembly: AssemblyCopyright("Copyright © Facebook 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: Guid("c186053a-741f-477d-b031-4d343fb20d1d")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout.Tests
|
||||
{
|
||||
/**
|
||||
* Generated constants used in {@link LayoutEngineTest}.
|
||||
*/
|
||||
public class TestConstants
|
||||
{
|
||||
|
||||
/** START_GENERATED **/
|
||||
public static readonly float SMALL_WIDTH = 35f;
|
||||
public static readonly float SMALL_HEIGHT = 18f;
|
||||
public static readonly float BIG_WIDTH = 172f;
|
||||
public static readonly float BIG_HEIGHT = 36f;
|
||||
public static readonly float BIG_MIN_WIDTH = 100f;
|
||||
public static readonly string SMALL_TEXT = "small";
|
||||
public static readonly string LONG_TEXT = "loooooooooong with space";
|
||||
public static readonly string MEASURE_WITH_RATIO_2 = "measureWithRatio2";
|
||||
public static readonly string MEASURE_WITH_MATCH_PARENT = "measureWithMatchParent";
|
||||
/** END_GENERATED **/
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="2.6.4" targetFramework="net45" />
|
||||
</packages>
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.CSSLayout", "Facebook.CSSLayout\Facebook.CSSLayout.csproj", "{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facebook.CSSLayout.Tests", "Facebook.CSSLayout.Tests\Facebook.CSSLayout.Tests.csproj", "{E687C8FD-0A0D-450F-853D-EC301BE1C038}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{29A6932B-FDDC-4E8A-8895-7FD64CC47B7F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
..\CSharpTranspiler.js = ..\CSharpTranspiler.js
|
||||
..\JavaTranspiler.js = ..\JavaTranspiler.js
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E687C8FD-0A0D-450F-853D-EC301BE1C038}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
static class Assertions
|
||||
{
|
||||
public static T assertNotNull<T>(T v) where T : class
|
||||
{
|
||||
Debug.Assert(v != null);
|
||||
return v;
|
||||
}
|
||||
|
||||
public static void assertCondition(bool condition, string explanation)
|
||||
{
|
||||
Debug.Assert(condition, explanation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
sealed class CSSCachedMeasurement
|
||||
{
|
||||
public float availableWidth;
|
||||
public float availableHeight;
|
||||
public CSSMeasureMode? widthMeasureMode = null;
|
||||
public CSSMeasureMode? heightMeasureMode = null;
|
||||
|
||||
public float computedWidth;
|
||||
public float computedHeight;
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public static class CSSConstants
|
||||
{
|
||||
public const float Undefined = float.NaN;
|
||||
|
||||
public static bool IsUndefined(float value)
|
||||
{
|
||||
return float.IsNaN(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSDirection
|
||||
{
|
||||
Inherit,
|
||||
LTR,
|
||||
RTL
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSFlexDirection
|
||||
{
|
||||
Column,
|
||||
ColumnReverse,
|
||||
Row,
|
||||
RowReverse
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSJustify
|
||||
{
|
||||
FlexStart,
|
||||
Center,
|
||||
FlexEnd,
|
||||
SpaceBetween,
|
||||
SpaceAround
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
|
||||
/**
|
||||
* Where the output of {@link LayoutEngine#layoutNode(CSSNode, float)} will go in the CSSNode.
|
||||
*/
|
||||
|
||||
class CSSLayout
|
||||
{
|
||||
// This value was chosen based on empiracle data. Even the most complicated
|
||||
// layouts should not require more than 16 entries to fit within the cache.
|
||||
public const int MAX_CACHED_RESULT_COUNT = 16;
|
||||
|
||||
public const int POSITION_LEFT = 0;
|
||||
public const int POSITION_TOP = 1;
|
||||
public const int POSITION_RIGHT = 2;
|
||||
public const int POSITION_BOTTOM = 3;
|
||||
|
||||
public const int DIMENSION_WIDTH = 0;
|
||||
public const int DIMENSION_HEIGHT = 1;
|
||||
|
||||
public float[] position = new float[4];
|
||||
public float[] dimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
public CSSDirection direction = CSSDirection.LTR;
|
||||
|
||||
public float flexBasis;
|
||||
|
||||
public int generationCount;
|
||||
public CSSDirection? lastParentDirection;
|
||||
|
||||
public int nextCachedMeasurementsIndex;
|
||||
public CSSCachedMeasurement[] cachedMeasurements = new CSSCachedMeasurement[MAX_CACHED_RESULT_COUNT];
|
||||
public float[] measuredDimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public CSSCachedMeasurement cachedLayout = new CSSCachedMeasurement();
|
||||
|
||||
public void resetResult()
|
||||
{
|
||||
FillArray(position, 0);
|
||||
FillArray(dimensions, CSSConstants.Undefined);
|
||||
|
||||
direction = CSSDirection.LTR;
|
||||
|
||||
flexBasis = 0;
|
||||
|
||||
generationCount = 0;
|
||||
lastParentDirection = null;
|
||||
|
||||
nextCachedMeasurementsIndex = 0;
|
||||
measuredDimensions[DIMENSION_WIDTH] = CSSConstants.Undefined;
|
||||
measuredDimensions[DIMENSION_HEIGHT] = CSSConstants.Undefined;
|
||||
|
||||
cachedLayout.widthMeasureMode = null;
|
||||
cachedLayout.heightMeasureMode = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "layout: {" +
|
||||
"left: " + position[POSITION_LEFT] + ", " +
|
||||
"top: " + position[POSITION_TOP] + ", " +
|
||||
"width: " + dimensions[DIMENSION_WIDTH] + ", " +
|
||||
"height: " + dimensions[DIMENSION_HEIGHT] + ", " +
|
||||
"direction: " + direction +
|
||||
"}";
|
||||
}
|
||||
|
||||
static void FillArray<T>(T[] array, T value)
|
||||
{
|
||||
for (var i = 0; i != array.Length; ++i)
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
|
||||
/**
|
||||
* A context for holding values local to a given instance of layout computation.
|
||||
*
|
||||
* This is necessary for making layout thread-safe. A separate instance should
|
||||
* be used when {@link CSSNode#calculateLayout} is called concurrently on
|
||||
* different node hierarchies.
|
||||
*/
|
||||
|
||||
sealed class CSSLayoutContext
|
||||
{
|
||||
/*package*/
|
||||
public MeasureOutput measureOutput = new MeasureOutput();
|
||||
public int currentGenerationCount;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSMeasureMode
|
||||
{
|
||||
Undefined,
|
||||
Exactly,
|
||||
AtMost,
|
||||
}
|
||||
}
|
|
@ -1,558 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* Should measure the given node and put the result in the given MeasureOutput.
|
||||
*/
|
||||
|
||||
public delegate MeasureOutput MeasureFunction(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
|
||||
|
||||
/**
|
||||
* A CSS Node. It has a style object you can manipulate at {@link #style}. After calling
|
||||
* {@link #calculateLayout()}, {@link #layout} will be filled with the results of the layout.
|
||||
*/
|
||||
|
||||
public class CSSNode
|
||||
{
|
||||
const int POSITION_LEFT = CSSLayout.POSITION_LEFT;
|
||||
const int POSITION_TOP = CSSLayout.POSITION_TOP;
|
||||
const int POSITION_RIGHT = CSSLayout.POSITION_RIGHT;
|
||||
const int POSITION_BOTTOM = CSSLayout.POSITION_BOTTOM;
|
||||
const int DIMENSION_WIDTH = CSSLayout.DIMENSION_WIDTH;
|
||||
const int DIMENSION_HEIGHT = CSSLayout.DIMENSION_HEIGHT;
|
||||
|
||||
enum LayoutState
|
||||
{
|
||||
/**
|
||||
* Some property of this node or its children has changes and the current values in
|
||||
* {@link #layout} are not valid.
|
||||
*/
|
||||
DIRTY,
|
||||
|
||||
/**
|
||||
* This node has a new layout relative to the last time {@link #MarkLayoutSeen()} was called.
|
||||
*/
|
||||
HAS_NEW_LAYOUT,
|
||||
|
||||
/**
|
||||
* {@link #layout} is valid for the node's properties and this layout has been marked as
|
||||
* having been seen.
|
||||
*/
|
||||
UP_TO_DATE,
|
||||
}
|
||||
|
||||
internal readonly CSSStyle style = new CSSStyle();
|
||||
internal readonly CSSLayout layout = new CSSLayout();
|
||||
internal readonly CachedCSSLayout lastLayout = new CachedCSSLayout();
|
||||
|
||||
internal int lineIndex = 0;
|
||||
internal /*package*/ CSSNode nextChild;
|
||||
|
||||
// 4 is kinda arbitrary, but the default of 10 seems really high for an average View.
|
||||
readonly List<CSSNode> mChildren = new List<CSSNode>(4);
|
||||
[Nullable] CSSNode mParent;
|
||||
[Nullable] MeasureFunction mMeasureFunction = null;
|
||||
LayoutState mLayoutState = LayoutState.DIRTY;
|
||||
bool mIsTextNode = false;
|
||||
|
||||
public int ChildCount
|
||||
{
|
||||
get { return mChildren.Count; }
|
||||
}
|
||||
|
||||
public CSSNode this[int i]
|
||||
{
|
||||
get { return mChildren[i]; }
|
||||
}
|
||||
|
||||
public IEnumerable<CSSNode> Children
|
||||
{
|
||||
get { return mChildren; }
|
||||
}
|
||||
|
||||
public void AddChild(CSSNode child)
|
||||
{
|
||||
InsertChild(ChildCount, child);
|
||||
}
|
||||
|
||||
public void InsertChild(int i, CSSNode child)
|
||||
{
|
||||
if (child.mParent != null)
|
||||
{
|
||||
throw new InvalidOperationException("Child already has a parent, it must be removed first.");
|
||||
}
|
||||
|
||||
mChildren.Insert(i, child);
|
||||
child.mParent = this;
|
||||
dirty();
|
||||
}
|
||||
|
||||
public void RemoveChildAt(int i)
|
||||
{
|
||||
mChildren[i].mParent = null;
|
||||
mChildren.RemoveAt(i);
|
||||
dirty();
|
||||
}
|
||||
|
||||
public CSSNode Parent
|
||||
{
|
||||
[return: Nullable]
|
||||
get
|
||||
{ return mParent; }
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index of the given child, or -1 if the child doesn't exist in this node.
|
||||
*/
|
||||
|
||||
public int IndexOf(CSSNode child)
|
||||
{
|
||||
return mChildren.IndexOf(child);
|
||||
}
|
||||
|
||||
public MeasureFunction MeasureFunction
|
||||
{
|
||||
get { return mMeasureFunction; }
|
||||
set
|
||||
{
|
||||
if (!valuesEqual(mMeasureFunction, value))
|
||||
{
|
||||
mMeasureFunction = value;
|
||||
dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTextNode
|
||||
{
|
||||
get { return mIsTextNode; }
|
||||
set { mIsTextNode = value; }
|
||||
}
|
||||
|
||||
public bool IsMeasureDefined
|
||||
{
|
||||
get { return mMeasureFunction != null; }
|
||||
}
|
||||
|
||||
internal MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode)
|
||||
{
|
||||
if (!IsMeasureDefined)
|
||||
{
|
||||
throw new Exception("Measure function isn't defined!");
|
||||
}
|
||||
return Assertions.assertNotNull(mMeasureFunction)(this, width, widthMode, height, heightMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual layout and saves the results in {@link #layout}
|
||||
*/
|
||||
|
||||
public void CalculateLayout()
|
||||
{
|
||||
LayoutEngine.layoutNode(DummyLayoutContext, this, CSSConstants.Undefined, CSSConstants.Undefined, null);
|
||||
}
|
||||
|
||||
static readonly CSSLayoutContext DummyLayoutContext = new CSSLayoutContext();
|
||||
|
||||
/**
|
||||
* See {@link LayoutState#DIRTY}.
|
||||
*/
|
||||
|
||||
public bool IsDirty
|
||||
{
|
||||
get { return mLayoutState == LayoutState.DIRTY; }
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link LayoutState#HAS_NEW_LAYOUT}.
|
||||
*/
|
||||
|
||||
public bool HasNewLayout
|
||||
{
|
||||
get { return mLayoutState == LayoutState.HAS_NEW_LAYOUT; }
|
||||
}
|
||||
|
||||
internal protected virtual void dirty()
|
||||
{
|
||||
if (mLayoutState == LayoutState.DIRTY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (mLayoutState == LayoutState.HAS_NEW_LAYOUT)
|
||||
{
|
||||
throw new InvalidOperationException("Previous layout was ignored! MarkLayoutSeen() never called");
|
||||
}
|
||||
|
||||
mLayoutState = LayoutState.DIRTY;
|
||||
|
||||
if (mParent != null)
|
||||
{
|
||||
mParent.dirty();
|
||||
}
|
||||
}
|
||||
|
||||
internal void markHasNewLayout()
|
||||
{
|
||||
mLayoutState = LayoutState.HAS_NEW_LAYOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the node that the current values in {@link #layout} have been seen. Subsequent calls
|
||||
* to {@link #hasNewLayout()} will return false until this node is laid out with new parameters.
|
||||
* You must call this each time the layout is generated if the node has a new layout.
|
||||
*/
|
||||
|
||||
public void MarkLayoutSeen()
|
||||
{
|
||||
if (!HasNewLayout)
|
||||
{
|
||||
throw new InvalidOperationException("Expected node to have a new layout to be seen!");
|
||||
}
|
||||
|
||||
mLayoutState = LayoutState.UP_TO_DATE;
|
||||
}
|
||||
|
||||
void toStringWithIndentation(StringBuilder result, int level)
|
||||
{
|
||||
// Spaces and tabs are dropped by IntelliJ logcat integration, so rely on __ instead.
|
||||
StringBuilder indentation = new StringBuilder();
|
||||
for (int i = 0; i < level; ++i)
|
||||
{
|
||||
indentation.Append("__");
|
||||
}
|
||||
|
||||
result.Append(indentation.ToString());
|
||||
result.Append(layout.ToString());
|
||||
|
||||
if (ChildCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
result.Append(", children: [\n");
|
||||
for (var i = 0; i < ChildCount; i++)
|
||||
{
|
||||
this[i].toStringWithIndentation(result, level + 1);
|
||||
result.Append("\n");
|
||||
}
|
||||
result.Append(indentation + "]");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
this.toStringWithIndentation(sb, 0);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
protected bool valuesEqual(float f1, float f2)
|
||||
{
|
||||
return FloatUtil.floatsEqual(f1, f2);
|
||||
}
|
||||
|
||||
protected bool valuesEqual<T>([Nullable] T o1, [Nullable] T o2)
|
||||
{
|
||||
if (o1 == null)
|
||||
{
|
||||
return o2 == null;
|
||||
}
|
||||
return o1.Equals(o2);
|
||||
}
|
||||
|
||||
public CSSDirection Direction
|
||||
{
|
||||
get { return style.direction; }
|
||||
set { updateDiscreteValue(ref style.direction, value); }
|
||||
}
|
||||
|
||||
public CSSFlexDirection FlexDirection
|
||||
{
|
||||
get { return style.flexDirection; }
|
||||
set { updateDiscreteValue(ref style.flexDirection, value); }
|
||||
}
|
||||
|
||||
public CSSJustify JustifyContent
|
||||
{
|
||||
get { return style.justifyContent; }
|
||||
set { updateDiscreteValue(ref style.justifyContent, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignContent
|
||||
{
|
||||
get { return style.alignContent; }
|
||||
set { updateDiscreteValue(ref style.alignContent, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignItems
|
||||
{
|
||||
get { return style.alignItems; }
|
||||
set { updateDiscreteValue(ref style.alignItems, value); }
|
||||
}
|
||||
|
||||
public CSSAlign AlignSelf
|
||||
{
|
||||
get { return style.alignSelf; }
|
||||
set { updateDiscreteValue(ref style.alignSelf, value); }
|
||||
}
|
||||
|
||||
public CSSPositionType PositionType
|
||||
{
|
||||
get { return style.positionType; }
|
||||
set { updateDiscreteValue(ref style.positionType, value); }
|
||||
}
|
||||
|
||||
public CSSWrap Wrap
|
||||
{
|
||||
get { return style.flexWrap; }
|
||||
set { updateDiscreteValue(ref style.flexWrap, value); }
|
||||
}
|
||||
|
||||
public float Flex
|
||||
{
|
||||
get { return style.flex; }
|
||||
set { updateFloatValue(ref style.flex, value); }
|
||||
}
|
||||
|
||||
public CSSOverflow Overflow
|
||||
{
|
||||
get { return style.overflow; }
|
||||
set { updateDiscreteValue(ref style.overflow, value); }
|
||||
}
|
||||
|
||||
public void SetMargin(CSSSpacingType spacingType, float margin)
|
||||
{
|
||||
if (style.margin.set((int)spacingType, margin))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetMargin(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.margin.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public void SetPadding(CSSSpacingType spacingType, float padding)
|
||||
{
|
||||
if (style.padding.set((int)spacingType, padding))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetPadding(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.padding.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public void SetBorder(CSSSpacingType spacingType, float border)
|
||||
{
|
||||
if (style.border.set((int)spacingType, border))
|
||||
dirty();
|
||||
}
|
||||
|
||||
public float GetBorder(CSSSpacingType spacingType)
|
||||
{
|
||||
return style.border.getRaw((int)spacingType);
|
||||
}
|
||||
|
||||
public float PositionTop
|
||||
{
|
||||
get { return style.position[POSITION_TOP]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_TOP], value); }
|
||||
}
|
||||
|
||||
public float PositionBottom
|
||||
{
|
||||
get { return style.position[POSITION_BOTTOM]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_BOTTOM], value); }
|
||||
}
|
||||
|
||||
public float PositionLeft
|
||||
{
|
||||
get { return style.position[POSITION_LEFT]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_LEFT], value); }
|
||||
}
|
||||
|
||||
public float PositionRight
|
||||
{
|
||||
get { return style.position[POSITION_RIGHT]; }
|
||||
set { updateFloatValue(ref style.position[POSITION_RIGHT], value); }
|
||||
}
|
||||
|
||||
public float Width
|
||||
{
|
||||
get { return style.dimensions[DIMENSION_WIDTH]; }
|
||||
set { updateFloatValue(ref style.dimensions[DIMENSION_WIDTH], value); }
|
||||
}
|
||||
|
||||
public float Height
|
||||
{
|
||||
get { return style.dimensions[DIMENSION_HEIGHT]; }
|
||||
set { updateFloatValue(ref style.dimensions[DIMENSION_HEIGHT], value); }
|
||||
}
|
||||
|
||||
public float MinWidth
|
||||
{
|
||||
get { return style.minWidth; }
|
||||
set { updateFloatValue(ref style.minWidth, value); }
|
||||
}
|
||||
|
||||
public float MinHeight
|
||||
{
|
||||
get { return style.minHeight; }
|
||||
set { updateFloatValue(ref style.minHeight, value); }
|
||||
}
|
||||
|
||||
public float MaxWidth
|
||||
{
|
||||
get { return style.maxWidth; }
|
||||
set { updateFloatValue(ref style.maxWidth, value); }
|
||||
}
|
||||
|
||||
public float MaxHeight
|
||||
{
|
||||
get { return style.maxHeight; }
|
||||
set { updateFloatValue(ref style.maxHeight, value); }
|
||||
}
|
||||
|
||||
public float LayoutX
|
||||
{
|
||||
get { return layout.position[POSITION_LEFT]; }
|
||||
}
|
||||
|
||||
public float LayoutY
|
||||
{
|
||||
get { return layout.position[POSITION_TOP]; }
|
||||
}
|
||||
|
||||
public float LayoutWidth
|
||||
{
|
||||
get { return layout.dimensions[DIMENSION_WIDTH]; }
|
||||
}
|
||||
|
||||
public float LayoutHeight
|
||||
{
|
||||
get { return layout.dimensions[DIMENSION_HEIGHT]; }
|
||||
}
|
||||
|
||||
public CSSDirection LayoutDirection
|
||||
{
|
||||
get { return layout.direction; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a default padding (left/top/right/bottom) for this node.
|
||||
*/
|
||||
public void SetDefaultPadding(CSSSpacingType spacingType, float padding)
|
||||
{
|
||||
if (style.padding.setDefault((int)spacingType, padding))
|
||||
dirty();
|
||||
}
|
||||
|
||||
void updateDiscreteValue<ValueT>(ref ValueT valueRef, ValueT newValue)
|
||||
{
|
||||
if (valuesEqual(valueRef, newValue))
|
||||
return;
|
||||
|
||||
valueRef = newValue;
|
||||
dirty();
|
||||
}
|
||||
|
||||
void updateFloatValue(ref float valueRef, float newValue)
|
||||
{
|
||||
if (valuesEqual(valueRef, newValue))
|
||||
return;
|
||||
valueRef = newValue;
|
||||
dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CSSNodeExtensions
|
||||
{
|
||||
/*
|
||||
Explicitly mark this node as dirty.
|
||||
|
||||
Calling this function is required when the measure function points to the same instance,
|
||||
but changes its behavior.
|
||||
|
||||
For all other property changes, the node is automatically marked dirty.
|
||||
*/
|
||||
|
||||
public static void MarkDirty(this CSSNode node)
|
||||
{
|
||||
node.dirty();
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CSSNodeExtensionsInternal
|
||||
{
|
||||
public static CSSNode getParent(this CSSNode node)
|
||||
{
|
||||
return node.Parent;
|
||||
}
|
||||
|
||||
public static int getChildCount(this CSSNode node)
|
||||
{
|
||||
return node.ChildCount;
|
||||
}
|
||||
|
||||
public static CSSNode getChildAt(this CSSNode node, int i)
|
||||
{
|
||||
return node[i];
|
||||
}
|
||||
|
||||
public static void addChildAt(this CSSNode node, CSSNode child, int i)
|
||||
{
|
||||
node.InsertChild(i, child);
|
||||
}
|
||||
|
||||
public static void removeChildAt(this CSSNode node, int i)
|
||||
{
|
||||
node.RemoveChildAt(i);
|
||||
}
|
||||
|
||||
public static void setMeasureFunction(this CSSNode node, MeasureFunction measureFunction)
|
||||
{
|
||||
node.MeasureFunction = measureFunction;
|
||||
}
|
||||
|
||||
public static void setIsTextNode(this CSSNode node, bool isTextNode)
|
||||
{
|
||||
node.IsTextNode = isTextNode;
|
||||
}
|
||||
|
||||
public static void calculateLayout(this CSSNode node)
|
||||
{
|
||||
node.CalculateLayout();
|
||||
}
|
||||
|
||||
public static bool isDirty(this CSSNode node)
|
||||
{
|
||||
return node.IsDirty;
|
||||
}
|
||||
|
||||
public static void setMargin(this CSSNode node, int spacingType, float margin)
|
||||
{
|
||||
node.SetMargin((CSSSpacingType)spacingType, margin);
|
||||
}
|
||||
|
||||
public static void setPadding(this CSSNode node, int spacingType, float padding)
|
||||
{
|
||||
node.SetPadding((CSSSpacingType)spacingType, padding);
|
||||
}
|
||||
|
||||
public static void setBorder(this CSSNode node, int spacingType, float border)
|
||||
{
|
||||
node.SetBorder((CSSSpacingType)spacingType, border);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSOverflow
|
||||
{
|
||||
Visible,
|
||||
Hidden
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSPositionType
|
||||
{
|
||||
Relative,
|
||||
Absolute
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSSpacingType
|
||||
{
|
||||
Left = 0,
|
||||
Top = 1,
|
||||
Right = 2,
|
||||
Bottom = 3,
|
||||
Vertical = 4,
|
||||
Horizontal = 5,
|
||||
Start = 6,
|
||||
End = 7,
|
||||
All = 8
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* The CSS style definition for a {@link CSSNode}.
|
||||
*/
|
||||
sealed class CSSStyle
|
||||
{
|
||||
public CSSDirection direction = CSSDirection.Inherit;
|
||||
public CSSFlexDirection flexDirection = CSSFlexDirection.Column;
|
||||
public CSSJustify justifyContent = CSSJustify.FlexStart;
|
||||
public CSSAlign alignContent = CSSAlign.FlexStart;
|
||||
public CSSAlign alignItems = CSSAlign.Stretch;
|
||||
public CSSAlign alignSelf = CSSAlign.Auto;
|
||||
public CSSPositionType positionType = CSSPositionType.Relative;
|
||||
public CSSWrap flexWrap = CSSWrap.NoWrap;
|
||||
public CSSOverflow overflow = CSSOverflow.Visible;
|
||||
public float flex;
|
||||
|
||||
public Spacing margin = new Spacing();
|
||||
public Spacing padding = new Spacing();
|
||||
public Spacing border = new Spacing();
|
||||
|
||||
public float[] position = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public float[] dimensions = {
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
|
||||
public float minWidth = CSSConstants.Undefined;
|
||||
public float minHeight = CSSConstants.Undefined;
|
||||
|
||||
public float maxWidth = CSSConstants.Undefined;
|
||||
public float maxHeight = CSSConstants.Undefined;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
public enum CSSWrap
|
||||
{
|
||||
NoWrap,
|
||||
Wrap
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* CSSLayout with additional information about the conditions under which it was generated.
|
||||
* {@link #RequestedWidth} and {@link #RequestedHeight} are the width and height the parent set on
|
||||
* this node before calling layout visited us.
|
||||
*/
|
||||
|
||||
class CachedCSSLayout : CSSLayout
|
||||
{
|
||||
public float requestedWidth = CSSConstants.Undefined;
|
||||
public float requestedHeight = CSSConstants.Undefined;
|
||||
public float parentMaxWidth = CSSConstants.Undefined;
|
||||
public float parentMaxHeight = CSSConstants.Undefined;
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{D534FB4B-A7D4-4A29-96D3-F39A91A259BD}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Facebook.CSSLayout</RootNamespace>
|
||||
<AssemblyName>Facebook.CSSLayout</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<LangVersion>5</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- A reference to the entire .NET Framework is automatically included -->
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Assertions.cs" />
|
||||
<Compile Include="CachedCSSLayout.cs" />
|
||||
<Compile Include="CSSAlign.cs" />
|
||||
<Compile Include="CSSCachedMeasurement.cs" />
|
||||
<Compile Include="CSSConstants.cs" />
|
||||
<Compile Include="CSSDirection.cs" />
|
||||
<Compile Include="CSSFlexDirection.cs" />
|
||||
<Compile Include="CSSJustify.cs" />
|
||||
<Compile Include="CSSLayout.cs" />
|
||||
<Compile Include="CSSLayoutContext.cs" />
|
||||
<Compile Include="CSSMeasureMode.cs" />
|
||||
<Compile Include="CSSNode.cs" />
|
||||
<Compile Include="CSSOverflow.cs" />
|
||||
<Compile Include="CSSPositionType.cs" />
|
||||
<Compile Include="CSSStyle.cs" />
|
||||
<Compile Include="CSSWrap.cs" />
|
||||
<Compile Include="FloatUtil.cs" />
|
||||
<Compile Include="LayoutEngine.cs" />
|
||||
<Compile Include="MeasureOutput.cs" />
|
||||
<Compile Include="NullableAttribute.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Spacing.cs" />
|
||||
<Compile Include="CSSSpacingType.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>$id$</id>
|
||||
<version>$version$</version>
|
||||
<title>$title$</title>
|
||||
<authors>$author$</authors>
|
||||
<owners>$author$</owners>
|
||||
<licenseUrl>https://github.com/facebook/css-layout/blob/master/LICENSE</licenseUrl>
|
||||
<projectUrl>https://github.com/facebook/css-layout</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>$description$</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright 2015 Facebook</copyright>
|
||||
<tags>flexbox flex-box css layout css-layout facebook</tags>
|
||||
</metadata>
|
||||
</package>
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
static class FloatUtil
|
||||
{
|
||||
const float Epsilon = .00001f;
|
||||
|
||||
public static bool floatsEqual(float f1, float f2)
|
||||
{
|
||||
if (float.IsNaN(f1) || float.IsNaN(f2))
|
||||
{
|
||||
return float.IsNaN(f1) && float.IsNaN(f2);
|
||||
}
|
||||
return Math.Abs(f2 - f1) < Epsilon;
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* POJO to hold the output of the measure function.
|
||||
*/
|
||||
public struct MeasureOutput
|
||||
{
|
||||
public MeasureOutput(float width, float height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
public readonly float Width;
|
||||
public readonly float Height;
|
||||
|
||||
internal float width
|
||||
{
|
||||
get { return Width; }
|
||||
}
|
||||
|
||||
internal float height
|
||||
{
|
||||
get { return Height; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* This is here to preserve the @nullable attribute of the original Java API.
|
||||
*/
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.Parameter)]
|
||||
sealed class NullableAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: AssemblyTitle("Facebook.CSSLayout")]
|
||||
[assembly: AssemblyDescription("A subset of CSS's flexbox layout algorithm and box model.")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Facebook")]
|
||||
[assembly: AssemblyProduct("Facebook.CSSLayout")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015 Facebook")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Facebook.CSSLayout.Tests")]
|
|
@ -1,234 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Facebook.CSSLayout
|
||||
{
|
||||
/**
|
||||
* Class representing CSS spacing (padding, margin, and borders). This is mostly necessary to
|
||||
* properly implement interactions and updates for properties like margin, marginLeft, and
|
||||
* marginHorizontal.
|
||||
*/
|
||||
|
||||
sealed class Spacing
|
||||
{
|
||||
/**
|
||||
* Spacing type that represents the left direction. E.g. {@code marginLeft}.
|
||||
*/
|
||||
internal const int LEFT = (int)CSSSpacingType.Left;
|
||||
/**
|
||||
* Spacing type that represents the top direction. E.g. {@code marginTop}.
|
||||
*/
|
||||
internal const int TOP = (int)CSSSpacingType.Top;
|
||||
/**
|
||||
* Spacing type that represents the right direction. E.g. {@code marginRight}.
|
||||
*/
|
||||
internal const int RIGHT = (int)CSSSpacingType.Right;
|
||||
/**
|
||||
* Spacing type that represents the bottom direction. E.g. {@code marginBottom}.
|
||||
*/
|
||||
internal const int BOTTOM = (int)CSSSpacingType.Bottom;
|
||||
/**
|
||||
* Spacing type that represents vertical direction (top and bottom). E.g. {@code marginVertical}.
|
||||
*/
|
||||
internal const int VERTICAL = (int)CSSSpacingType.Vertical;
|
||||
/**
|
||||
* Spacing type that represents horizontal direction (left and right). E.g.
|
||||
* {@code marginHorizontal}.
|
||||
*/
|
||||
internal const int HORIZONTAL = (int)CSSSpacingType.Horizontal;
|
||||
/**
|
||||
* Spacing type that represents start direction e.g. left in left-to-right, right in right-to-left.
|
||||
*/
|
||||
internal const int START = (int)CSSSpacingType.Start;
|
||||
/**
|
||||
* Spacing type that represents end direction e.g. right in left-to-right, left in right-to-left.
|
||||
*/
|
||||
internal const int END = (int)CSSSpacingType.End;
|
||||
/**
|
||||
* Spacing type that represents all directions (left, top, right, bottom). E.g. {@code margin}.
|
||||
*/
|
||||
internal const int ALL = (int)CSSSpacingType.All;
|
||||
|
||||
static readonly int[] sFlagsMap = {
|
||||
1, /*LEFT*/
|
||||
2, /*TOP*/
|
||||
4, /*RIGHT*/
|
||||
8, /*BOTTOM*/
|
||||
16, /*VERTICAL*/
|
||||
32, /*HORIZONTAL*/
|
||||
64, /*START*/
|
||||
128, /*END*/
|
||||
256 /*ALL*/
|
||||
};
|
||||
|
||||
float[] mSpacing = newFullSpacingArray();
|
||||
[Nullable] float[] mDefaultSpacing = null;
|
||||
int mValueFlags = 0;
|
||||
bool mHasAliasesSet;
|
||||
|
||||
/**
|
||||
* Set a spacing value.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
|
||||
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
|
||||
* @param value the value for this direction
|
||||
* @return {@code true} if the spacing has changed, or {@code false} if the same value was already
|
||||
* set
|
||||
*/
|
||||
|
||||
internal bool set(int spacingType, float value)
|
||||
{
|
||||
if (!FloatUtil.floatsEqual(mSpacing[spacingType], value))
|
||||
{
|
||||
mSpacing[spacingType] = value;
|
||||
|
||||
if (CSSConstants.IsUndefined(value))
|
||||
{
|
||||
mValueFlags &= ~sFlagsMap[spacingType];
|
||||
}
|
||||
else
|
||||
{
|
||||
mValueFlags |= sFlagsMap[spacingType];
|
||||
}
|
||||
|
||||
mHasAliasesSet =
|
||||
(mValueFlags & sFlagsMap[ALL]) != 0 ||
|
||||
(mValueFlags & sFlagsMap[VERTICAL]) != 0 ||
|
||||
(mValueFlags & sFlagsMap[HORIZONTAL]) != 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a default spacing value. This is used as a fallback when no spacing has been set for a
|
||||
* particular direction.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
|
||||
* @param value the default value for this direction
|
||||
* @return
|
||||
*/
|
||||
|
||||
internal bool setDefault(int spacingType, float value)
|
||||
{
|
||||
if (mDefaultSpacing == null)
|
||||
mDefaultSpacing = newSpacingResultArray();
|
||||
|
||||
if (!FloatUtil.floatsEqual(mDefaultSpacing[spacingType], value))
|
||||
{
|
||||
mDefaultSpacing[spacingType] = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the spacing for a direction. This takes into account any default values that have been set.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM}
|
||||
*/
|
||||
|
||||
internal float get(int spacingType)
|
||||
{
|
||||
float defaultValue =
|
||||
(mDefaultSpacing != null)
|
||||
? mDefaultSpacing[spacingType]
|
||||
: (spacingType == START || spacingType == END ? CSSConstants.Undefined : 0);
|
||||
|
||||
if (mValueFlags == 0)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if ((mValueFlags & sFlagsMap[spacingType]) != 0)
|
||||
{
|
||||
return mSpacing[spacingType];
|
||||
}
|
||||
|
||||
if (mHasAliasesSet)
|
||||
{
|
||||
int secondType = spacingType == TOP || spacingType == BOTTOM ? VERTICAL : HORIZONTAL;
|
||||
if ((mValueFlags & sFlagsMap[secondType]) != 0)
|
||||
{
|
||||
return mSpacing[secondType];
|
||||
}
|
||||
else if ((mValueFlags & sFlagsMap[ALL]) != 0)
|
||||
{
|
||||
return mSpacing[ALL];
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw value (that was set using {@link #set(int, float)}), without taking into account
|
||||
* any default values.
|
||||
*
|
||||
* @param spacingType one of {@link #LEFT}, {@link #TOP}, {@link #RIGHT}, {@link #BOTTOM},
|
||||
* {@link #VERTICAL}, {@link #HORIZONTAL}, {@link #ALL}
|
||||
*/
|
||||
|
||||
internal float getRaw(int spacingType)
|
||||
{
|
||||
return mSpacing[spacingType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get start value and fallback to given type if not defined. This is used privately
|
||||
* by the layout engine as a more efficient way to fetch direction-aware values by
|
||||
* avoid extra method invocations.
|
||||
*/
|
||||
internal float getWithFallback(int spacingType, int fallbackType)
|
||||
{
|
||||
return
|
||||
(mValueFlags & sFlagsMap[spacingType]) != 0
|
||||
? mSpacing[spacingType]
|
||||
: get(fallbackType);
|
||||
}
|
||||
|
||||
static float[] newFullSpacingArray()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined
|
||||
};
|
||||
}
|
||||
|
||||
static float[] newSpacingResultArray()
|
||||
{
|
||||
return newSpacingResultArray(0);
|
||||
}
|
||||
|
||||
static float[] newSpacingResultArray(float defaultValue)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
defaultValue,
|
||||
CSSConstants.Undefined,
|
||||
CSSConstants.Undefined,
|
||||
defaultValue
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
MSB=msbuild.exe /m /verbosity:m /nologo
|
||||
NUGET=nuget.exe
|
||||
NUNITC=nunit-console.exe
|
||||
|
||||
VER=1.0.0
|
||||
NAME=Facebook.CSSLayout
|
||||
|
||||
.PHONY: all
|
||||
all: test
|
||||
|
||||
.PHONY: distribute
|
||||
distribute: package release-package
|
||||
|
||||
.PHONY: package
|
||||
package: conf=Release
|
||||
package: build
|
||||
cd ${NAME} && ${NUGET} pack ${NAME}.csproj -Version ${VER} -Prop Configuration=${conf}
|
||||
|
||||
.PHONY: release-package
|
||||
release-package:
|
||||
cd ${NAME} && nuget push ${NAME}.${VER}.nupkg
|
||||
|
||||
.PHONY: test
|
||||
test: build-debug
|
||||
cd ${NAME}.Tests/bin/Debug && ${NUNITC} Facebook.CSSLayout.Tests.dll
|
||||
|
||||
.PHONY: build-debug
|
||||
build-debug: conf=Debug
|
||||
build-debug: build
|
||||
|
||||
.PHONY: build-release
|
||||
build-release: conf=Release
|
||||
build-release: build
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
${MSB} ${NAME}.sln /p:Configuration=${conf} /t:"Facebook_CSSLayout:Rebuild;Facebook_CSSLayout_Tests:Rebuild"
|
|
@ -1,29 +0,0 @@
|
|||
// UMD (Universal Module Definition)
|
||||
// See https://github.com/umdjs/umd for reference
|
||||
//
|
||||
// This file uses the following specific UMD implementation:
|
||||
// https://github.com/umdjs/umd/blob/master/templates/returnExports.js
|
||||
(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.computeLayout = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
// @@include('./Layout.js')
|
||||
|
||||
return function(node) {
|
||||
/*eslint-disable */
|
||||
// disabling ESLint because this code relies on the above include
|
||||
computeLayout.fillNodes(node);
|
||||
computeLayout.computeLayout(node);
|
||||
/*eslint-enable */
|
||||
};
|
||||
}));
|
|
@ -1 +0,0 @@
|
|||
css-layout
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<component name="CopyrightManager">
|
||||
<settings default="">
|
||||
<module2copyright />
|
||||
</settings>
|
||||
</component>
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/java.iml" filepath="$PROJECT_DIR$/java.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
|
@ -1,125 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.10.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -1,349 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var layoutTestUtils = require('./Layout-test-utils.js');
|
||||
var computeLayout = require('./Layout.js').layoutNodeImpl;
|
||||
var fs = require('fs');
|
||||
var JavaTranspiler = require('./JavaTranspiler.js');
|
||||
var CSharpTranspiler = require('./CSharpTranspiler.js');
|
||||
|
||||
var currentTest = '';
|
||||
var allTests = [];
|
||||
var computeDOMLayout = layoutTestUtils.computeDOMLayout;
|
||||
var reduceTest = layoutTestUtils.reduceTest;
|
||||
global.layoutTestUtils = {
|
||||
testLayout: function(node, expectedLayout) {
|
||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||
},
|
||||
testLayoutAgainstDomOnly: function() {
|
||||
},
|
||||
testRandomLayout: function(node, i) {
|
||||
allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)});
|
||||
},
|
||||
testLayoutAgainstExpectedOnly: function(node, expectedLayout) {
|
||||
allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout});
|
||||
},
|
||||
computeLayout: layoutTestUtils.computeLayout,
|
||||
reduceTest: reduceTest,
|
||||
text: layoutTestUtils.text,
|
||||
texts: layoutTestUtils.texts,
|
||||
textSizes: layoutTestUtils.textSizes,
|
||||
measureWithRatio2: layoutTestUtils.measureWithRatio2,
|
||||
measureWithMatchParent: layoutTestUtils.measureWithMatchParent
|
||||
};
|
||||
|
||||
global.describe = function(name, cb) {
|
||||
if (name.toLowerCase().indexOf('javascript only') === -1) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
global.it = function(name, cb) { currentTest = name; cb(); };
|
||||
global.xit = function() { /* ignore skipped tests */ };
|
||||
|
||||
require('./__tests__/Layout-test.js');
|
||||
|
||||
|
||||
function printLayout(test) {
|
||||
var level = 1;
|
||||
var res = [];
|
||||
|
||||
function indent(level) {
|
||||
var result = '';
|
||||
for (var i = 0; i < level; ++i) {
|
||||
result += ' ';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function add(str) {
|
||||
if (str.length > 0) {
|
||||
str = indent(level) + str;
|
||||
}
|
||||
res.push(str);
|
||||
}
|
||||
|
||||
function isEmpty(obj) {
|
||||
return !Object.keys(obj).length;
|
||||
}
|
||||
|
||||
add('{');
|
||||
level++;
|
||||
|
||||
// Output the style node
|
||||
add('css_node_t *root_node = new_test_css_node();');
|
||||
add('{');
|
||||
level++;
|
||||
if (!isEmpty(test.node.style) || test.node.children && test.node.children.length) {
|
||||
add('css_node_t *node_0 = root_node;');
|
||||
}
|
||||
function recStyle(node) {
|
||||
|
||||
function addStyle(str) {
|
||||
add('node_' + (level - 3) + '->style.' + str);
|
||||
}
|
||||
|
||||
function addEnum(node, jsKey, cKey, dict) {
|
||||
if (jsKey in node.style) {
|
||||
addStyle(cKey + ' = ' + dict[node.style[jsKey]] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
function addFloat(node, jsKey, cKey) {
|
||||
if (jsKey in node.style) {
|
||||
addStyle(cKey + ' = ' + node.style[jsKey] + ';');
|
||||
}
|
||||
}
|
||||
|
||||
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]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_START]');
|
||||
addFloat(node, spacing + suffix, spacing + '[CSS_END]');
|
||||
|
||||
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]');
|
||||
addFloat(node, spacing + 'Start' + suffix, spacing + '[CSS_START]');
|
||||
addFloat(node, spacing + 'End' + suffix, spacing + '[CSS_END]');
|
||||
}
|
||||
|
||||
function addMeasure(node) {
|
||||
if ('measure' in node.style) {
|
||||
if (node.children && node.children.length) {
|
||||
throw new Error('Using custom measure function is supported only for leaf nodes.');
|
||||
}
|
||||
add('node_' + (level - 3) + '->measure = measure;');
|
||||
add('node_' + (level - 3) + '->context = "' + node.style.measure.toString() + '";');
|
||||
}
|
||||
}
|
||||
|
||||
addEnum(node, 'direction', 'direction', {
|
||||
'ltr': 'CSS_DIRECTION_LTR',
|
||||
'rtl': 'CSS_DIRECTION_RTL'
|
||||
});
|
||||
addEnum(node, 'flexDirection', 'flex_direction', {
|
||||
'row': 'CSS_FLEX_DIRECTION_ROW',
|
||||
'row-reverse': 'CSS_FLEX_DIRECTION_ROW_REVERSE',
|
||||
'column': 'CSS_FLEX_DIRECTION_COLUMN',
|
||||
'column-reverse': 'CSS_FLEX_DIRECTION_COLUMN_REVERSE'
|
||||
});
|
||||
addEnum(node, 'justifyContent', 'justify_content', {
|
||||
'flex-start': 'CSS_JUSTIFY_FLEX_START',
|
||||
'center': 'CSS_JUSTIFY_CENTER',
|
||||
'flex-end': 'CSS_JUSTIFY_FLEX_END',
|
||||
'space-between': 'CSS_JUSTIFY_SPACE_BETWEEN',
|
||||
'space-around': 'CSS_JUSTIFY_SPACE_AROUND'
|
||||
});
|
||||
addEnum(node, 'alignContent', 'align_content', {
|
||||
'flex-start': 'CSS_ALIGN_FLEX_START',
|
||||
'center': 'CSS_ALIGN_CENTER',
|
||||
'flex-end': 'CSS_ALIGN_FLEX_END',
|
||||
'stretch': 'CSS_ALIGN_STRETCH'
|
||||
});
|
||||
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'
|
||||
});
|
||||
addEnum(node, 'position', 'position_type', {
|
||||
'relative': 'CSS_POSITION_RELATIVE',
|
||||
'absolute': 'CSS_POSITION_ABSOLUTE'
|
||||
});
|
||||
addEnum(node, 'flexWrap', 'flex_wrap', {
|
||||
'nowrap': 'CSS_NOWRAP',
|
||||
'wrap': 'CSS_WRAP'
|
||||
});
|
||||
addEnum(node, 'measureMode', 'measure_mode', {
|
||||
'undefined': 'CSS_MEASURE_MODE_UNDEFINED',
|
||||
'exactly': 'CSS_MEASURE_MODE_EXACTLY',
|
||||
'at-most': 'CSS_MEASURE_MODE_AT_MOST'
|
||||
});
|
||||
addEnum(node, 'overflow', 'overflow', {
|
||||
'visible': 'CSS_OVERFLOW_VISIBLE',
|
||||
'hidden': 'CSS_OVERFLOW_HIDDEN'
|
||||
});
|
||||
addFloat(node, 'flex', 'flex');
|
||||
addFloat(node, 'width', 'dimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'height', 'dimensions[CSS_HEIGHT]');
|
||||
addFloat(node, 'maxWidth', 'maxDimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'maxHeight', 'maxDimensions[CSS_HEIGHT]');
|
||||
addFloat(node, 'minWidth', 'minDimensions[CSS_WIDTH]');
|
||||
addFloat(node, 'minHeight', 'minDimensions[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]');
|
||||
addMeasure(node);
|
||||
|
||||
if (node.children) {
|
||||
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_' + (level - 3) + ';');
|
||||
|
||||
for (var i = 0; i < node.children.length; ++i) {
|
||||
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
||||
recStyle(node.children[i]);
|
||||
}
|
||||
|
||||
level--;
|
||||
add('}');
|
||||
}
|
||||
}
|
||||
recStyle(test.node);
|
||||
level--;
|
||||
add('}');
|
||||
add('');
|
||||
|
||||
// Output the expected layout node
|
||||
add('css_node_t *root_layout = new_test_css_node();');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_0 = root_layout;');
|
||||
|
||||
function recLayout(node) {
|
||||
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 + ';');
|
||||
|
||||
if (node.children) {
|
||||
add('init_css_node_children(node_' + (level - 3) + ', ' + node.children.length + ');');
|
||||
add('{');
|
||||
level++;
|
||||
add('css_node_t *node_' + (level - 3) + ';');
|
||||
|
||||
for (var i = 0; i < node.children.length; ++i) {
|
||||
add('node_' + (level - 3) + ' = node_' + (level - 4) + '->get_child(node_' + (level - 4) + '->context, ' + i + ');');
|
||||
recLayout(node.children[i]);
|
||||
}
|
||||
|
||||
level--;
|
||||
add('}');
|
||||
}
|
||||
}
|
||||
recLayout(test.expectedLayout);
|
||||
level--;
|
||||
add('}');
|
||||
add('');
|
||||
|
||||
// Do the test
|
||||
add('test("' + test.name.replace(/"/g, '\\"') + '", root_node, root_layout);');
|
||||
level--;
|
||||
add('}');
|
||||
return res.join('\n');
|
||||
}
|
||||
|
||||
function transpileAnnotatedJStoC(jsCode) {
|
||||
return jsCode
|
||||
.replace(/'abs-layout'/g, '"abs-layout"')
|
||||
.replace(/'abs-measure'/g, '"abs-measure"')
|
||||
.replace(/'flex'/g, '"flex"')
|
||||
.replace(/'measure'/g, '"measure"')
|
||||
.replace(/'stretch'/g, '"stretch"')
|
||||
.replace('node.style.measure', 'node.measure')
|
||||
.replace(/undefined/g, 'NULL')
|
||||
.replace(/\.children\.length/g, '.children_count')
|
||||
.replace(/\.width/g, '.dimensions[CSS_WIDTH]')
|
||||
.replace(/\.height/g, '.dimensions[CSS_HEIGHT]')
|
||||
.replace(/\.maxWidth/g, '.maxDimensions[CSS_WIDTH]')
|
||||
.replace(/\.maxHeight/g, '.maxDimensions[CSS_HEIGHT]')
|
||||
.replace(/\.minWidth/g, '.minDimensions[CSS_WIDTH]')
|
||||
.replace(/\.minHeight/g, '.minDimensions[CSS_HEIGHT]')
|
||||
.replace(/\.lineIndex/g, '.line_index')
|
||||
.replace(/\.nextChild/g, '.next_child')
|
||||
.replace(/\.flexBasis/g, '.flex_basis')
|
||||
.replace(/layout\[pos/g, 'layout.position[pos')
|
||||
.replace(/layout\[leading/g, 'layout.position[leading')
|
||||
.replace(/layout\[trailing/g, 'layout.position[trailing')
|
||||
.replace(/layout\[measuredDim/g, 'layout.measured_dimensions[dim')
|
||||
.replace(/layout\.measuredWidth/g, 'layout.measured_dimensions[CSS_WIDTH]')
|
||||
.replace(/layout\.measuredHeight/g, 'layout.measured_dimensions[CSS_HEIGHT]')
|
||||
.replace(/style\[dim/g, 'style.dimensions[dim')
|
||||
.replace(/style\[CSS_LEFT/g, 'style.position[CSS_LEFT')
|
||||
.replace(/style\[CSS_TOP/g, 'style.position[CSS_TOP')
|
||||
.replace(/style\[CSS_RIGHT/g, 'style.position[CSS_RIGHT')
|
||||
.replace(/style\[CSS_BOTTOM/g, 'style.position[CSS_BOTTOM')
|
||||
.replace(/node.children\[i\]/g, 'node->get_child(node->context, i)')
|
||||
.replace(/node.children\[j\]/g, 'node->get_child(node->context, j)')
|
||||
.replace(/node\./g, 'node->')
|
||||
.replace(/child\./g, 'child->')
|
||||
.replace(/currentAbsoluteChild\./g, 'currentAbsoluteChild->')
|
||||
.replace(/currentRelativeChild\./g, 'currentRelativeChild->')
|
||||
.replace(/getPositionType\((.+?)\)/g, '$1->style.position_type')
|
||||
.replace(/getJustifyContent\((.+?)\)/g, '$1->style.justify_content')
|
||||
.replace(/getAlignContent\((.+?)\)/g, '$1->style.align_content')
|
||||
.replace(/assert\((.+?),\s*'(.+?)'\);/g, 'assert($1); // $2')
|
||||
.replace(/getOverflow\((.+?)\)/g, '$1->style.overflow')
|
||||
.replace(/var\/\*\(c\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/var\/\*([^\/]+)\*\//g, '$1')
|
||||
.replace(/ === /g, ' == ')
|
||||
.replace(/ !== /g, ' != ')
|
||||
.replace(/\n {2}/g, '\n')
|
||||
.replace(/\/\*\(c\)!([^*]+)\*\//g, '$1')
|
||||
.replace(/\/[*]!([^*]+)[*]\//g, '$1')
|
||||
.replace(/\/\*\(java\)!([^*]+)\*\//g, '');
|
||||
}
|
||||
|
||||
function makeConstDefs() {
|
||||
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 + '"',
|
||||
'#define MEASURE_WITH_RATIO_2 "' + layoutTestUtils.measureWithRatio2() + '"',
|
||||
'#define MEASURE_WITH_MATCH_PARENT "' + layoutTestUtils.measureWithMatchParent() + '"'
|
||||
];
|
||||
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);
|
||||
}
|
||||
|
||||
// Extract the function body by trimming the first ('function layoutNode(...) {') and
|
||||
// last ('}') lines. Also, start the function body with a blank line so that regexes
|
||||
// that use \n to match the start of a line will match the actual first line.
|
||||
var computeLayoutCode = [''].concat(computeLayout.toString().split('\n').slice(1, -1)).join('\n');
|
||||
|
||||
var allTestsInC = allTests.map(printLayout);
|
||||
generateFile(__dirname + '/__tests__/Layout-test.c', allTestsInC.join('\n\n'));
|
||||
generateFile(__dirname + '/Layout-test-utils.c', makeConstDefs());
|
||||
generateFile(__dirname + '/Layout.c', transpileAnnotatedJStoC(computeLayoutCode));
|
||||
generateFile(__dirname + '/java/src/com/facebook/csslayout/LayoutEngine.java', JavaTranspiler.transpileLayoutEngine(computeLayoutCode));
|
||||
generateFile(__dirname + '/java/tests/com/facebook/csslayout/TestConstants.java', JavaTranspiler.transpileCConstDefs(makeConstDefs()));
|
||||
generateFile(__dirname + '/java/tests/com/facebook/csslayout/LayoutEngineTest.java', JavaTranspiler.transpileCTestsArray(allTestsInC));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout/LayoutEngine.cs', CSharpTranspiler.transpileLayoutEngine(computeLayoutCode));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout.Tests/TestConstants.cs', CSharpTranspiler.transpileCConstDefs(makeConstDefs()));
|
||||
generateFile(__dirname + '/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs', CSharpTranspiler.transpileCTestsArray(allTestsInC));
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (c) 2014-present, 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.
|
||||
|
||||
import os
|
||||
import urllib2
|
||||
import zipfile
|
||||
|
||||
include_defs('//CSSLAYOUT_DEFS')
|
||||
|
||||
# Download gtest dep if it does not exists in path
|
||||
current_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
gtest_folder = 'googletest-release-1.7.0'
|
||||
if GTEST_DL_URL != None and not os.path.isdir(current_dir + gtest_folder):
|
||||
gtest = urllib2.urlopen('https://github.com/google/googletest/archive/release-1.7.0.zip').read()
|
||||
with open("gtest.zip", 'w') as f:
|
||||
f.write(gtest)
|
||||
with zipfile.ZipFile('gtest.zip',"r") as zip:
|
||||
zip.extractall(os.path.dirname(os.path.realpath(__file__)))
|
||||
os.remove('gtest.zip')
|
||||
|
||||
COMPILER_FLAGS = [
|
||||
'-std=c++11',
|
||||
'-Wno-missing-prototypes',
|
||||
]
|
||||
|
||||
cxx_library(
|
||||
name = 'gtest',
|
||||
srcs = glob([gtest_folder + '/src/*.cc']),
|
||||
exported_headers = subdir_glob([
|
||||
(gtest_folder + '/include', '**/*.h'),
|
||||
(gtest_folder, 'src/*.h'),
|
||||
(gtest_folder, 'src/*.cc'),
|
||||
]),
|
||||
header_namespace = '',
|
||||
compiler_flags = COMPILER_FLAGS,
|
||||
deps = [],
|
||||
visibility = [CSSLAYOUT_ROOT],
|
||||
)
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче