Skip to content

Instantly share code, notes, and snippets.

@mattpodwysocki
Last active November 7, 2016 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattpodwysocki/fa116dea4de07e6e36cdb1e05ce76d8a to your computer and use it in GitHub Desktop.
Save mattpodwysocki/fa116dea4de07e6e36cdb1e05ce76d8a to your computer and use it in GitHub Desktop.
#include "csslayoutnode.h"
Nan::Persistent<v8::Function> CSSLayoutNode::constructor;
CSSLayoutNode::CSSLayoutNode(v8::Local<v8::Object> self) {
this->_node = CSSNodeNew();
CSSNodeInit(this->_node);
CSSNodeSetContext(this->_node, *self);
}
CSSLayoutNode::~CSSLayoutNode() {
}
void CSSLayoutNode::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("CSSLayoutNode").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Nan::SetPrototypeMethod(tpl, "free", Free);
Nan::SetPrototypeMethod(tpl, "freeRecursive", FreeRecursive);
Nan::SetPrototypeMethod(tpl, "markDirty", MarkDirty);
Nan::SetMethod(tpl, "instanceCount", InstanceCount);
// CSS_NODE_PROPERTY
CSS_NODE_GETTER(isDirty, IsDirty);
CSSNODE_GETTER_SETTER(isTextNode, IsTextNode);
CSSNODE_GETTER_SETTER(hasNewLayout, HasNewLayout);
CSSNODE_GETTER_SETTER(measureFunction, MeasureFunction);
// CSS_NODE_STYLE_PROPERTY
CSSNODE_GETTER_SETTER(styleDirection, StyleDirection);
CSSNODE_GETTER_SETTER(flexDirection, FlexDirection);
CSSNODE_GETTER_SETTER(justifyContent, JustifyContent);
CSSNODE_GETTER_SETTER(alignContent, AlignContent);
CSSNODE_GETTER_SETTER(alignItems, AlignItems);
CSSNODE_GETTER_SETTER(alignSelf, AlignSelf);
CSSNODE_GETTER_SETTER(positionType, PositionType);
CSSNODE_GETTER_SETTER(wrap, Wrap);
CSSNODE_GETTER_SETTER(overflow, Overflow);
CSSNODE_GETTER_SETTER(flex, Flex);
CSSNODE_GETTER_SETTER(flexGrow, FlexGrow);
CSSNODE_GETTER_SETTER(flexShrink, FlexShrink);
CSSNODE_GETTER_SETTER(flexBasis, FlexBasis);
// CSS_NODE_STYLE_EDGE_PROPERTY
// CSS_NODE_STYLE_PROPERTY
CSSNODE_GETTER_SETTER(styleWidth, StyleWidth);
CSSNODE_GETTER_SETTER(styleHeight, StyleHeight);
CSSNODE_GETTER_SETTER(styleMinWidth, StyleMinWidth);
CSSNODE_GETTER_SETTER(styleMinHeight, StyleMinHeight);
CSSNODE_GETTER_SETTER(styleMaxWidth, StyleMaxWidth);
CSSNODE_GETTER_SETTER(styleMaxHeight, StyleMaxHeight);
// CSS_NODE_LAYOUT_PROPERTY
CSS_NODE_GETTER(layoutX, LayoutX);
CSS_NODE_GETTER(layoutY, LayoutY);
CSS_NODE_GETTER(layoutWidth, LayoutWidth);
CSS_NODE_GETTER(layoutHeight, LayoutHeight);
CSS_NODE_GETTER(layoutDirection, LayoutDirection);
constructor.Reset(tpl->GetFunction());
exports->Set(Nan::New("CSSLayoutNode").ToLocalChecked(), tpl->GetFunction());
}
NAN_METHOD(CSSLayoutNode::New) {
if (!info.IsConstructCall()) {
Nan::ThrowReferenceError("CSSLayoutNode requires new to instantiate.");
}
auto self = info.This();
CSSLayoutNode* obj = new CSSLayoutNode(self);
obj->Wrap(self);
info.GetReturnValue().Set(self);
}
NAN_METHOD(CSSLayoutNode::Free) {
CSSNODE_ASSERT
CSSNodeFree(obj->_node);
obj->_node = nullptr;
}
NAN_METHOD(CSSLayoutNode::FreeRecursive) {
CSSNODE_ASSERT
CSSNodeFreeRecursive(obj->_node);
obj->_node = nullptr;
}
NAN_METHOD(CSSLayoutNode::ValueIsUndefined) {
float value = static_cast<float>(info[0]->NumberValue());
info.GetReturnValue().Set(Nan::New(CSSValueIsUndefined(value)));
}
NAN_GETTER(CSSLayoutNode::GetIsDirty) {
CSSNODE_ASSERT
info.GetReturnValue().Set(Nan::New(CSSNodeIsDirty(obj->_node)));
}
NAN_METHOD(CSSLayoutNode::MarkDirty) {
CSSNODE_ASSERT
CSSNodeMarkDirty(obj->_node);
}
NAN_METHOD(CSSLayoutNode::InstanceCount) {
auto count = CSSNodeGetInstanceCount();
info.GetReturnValue().Set(Nan::New(count));
}
// CSS_NODE_PROPERTY
CSSNODE_PROP_BOOL(IsTextNode, IsTextnode);
CSSNODE_PROP_BOOL(HasNewLayout, HasNewLayout);
static CSSSize NativeMeasureFunc(void *context,
float width,
CSSMeasureMode widthMode,
float height,
CSSMeasureMode heightMode) {
v8::Local<v8::External> self = v8::External::New(v8::Isolate::GetCurrent(), context);
//CSSLayoutNode* obj = Nan::ObjectWrap::Unwrap<CSSLayoutNode>(self);
//const unsigned argc = 5;
//v8::Local<v8::Value> argv[argc] = {
// self,
// Nan::New(width),
// Nan::New((int32_t)widthMode),
// Nan::New(height),
// Nan::New((int32_t)heightMode)
//};
//auto localMeasure = v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), obj->_measure);
//const auto measureResult = static_cast<int64_t>(localMeasure->Call(Nan::GetCurrentContext()->Global(), argc, argv)->NumberValue());
const float measuredWidth = 0;//const float measuredWidth = static_cast<float>(0xFFFFFFFF & (measureResult >> 32));
const float measuredHeight = 0;//const float measuredHeight = static_cast<float>(0xFFFFFFFF & measureResult);
return CSSSize { measuredWidth, measuredHeight };
}
NAN_GETTER(CSSLayoutNode::GetMeasureFunction) {
CSSNODE_ASSERT
auto localMeasure = v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), obj->_measure);
info.GetReturnValue().Set(localMeasure);
}
NAN_SETTER(CSSLayoutNode::SetMeasureFunction) {
CSSNODE_ASSERT
if (value->IsNull() || value->IsUndefined()) {
obj->_measure.Empty();
CSSNodeSetMeasureFunc(obj->_node, nullptr);
} else if (!value->IsFunction()) {
Nan::ThrowTypeError("argument must be a function");
}
auto fn = v8::Handle<v8::Function>::Cast(value);
v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>> persistent(v8::Isolate::GetCurrent(), fn);
obj->_measure = persistent;
CSSNodeSetMeasureFunc(obj->_node, NativeMeasureFunc);
}
// CSS_NODE_STYLE_PROPERTY
CSSNODE_PROP_ENUM(StyleDirection, Direction, CSSDirection, 0, 2);
CSSNODE_PROP_ENUM(FlexDirection, FlexDirection, CSSFlexDirection, 0, 4);
CSSNODE_PROP_ENUM(JustifyContent, JustifyContent, CSSJustify, 0, 4);
CSSNODE_PROP_ENUM(AlignContent, AlignContent, CSSAlign, 0, 4);
CSSNODE_PROP_ENUM(AlignItems, AlignItems, CSSAlign, 0, 4);
CSSNODE_PROP_ENUM(AlignSelf, AlignSelf, CSSAlign, 0, 4);
CSSNODE_PROP_ENUM(PositionType, PositionType, CSSPositionType, 0, 1);
CSSNODE_PROP_ENUM(Wrap, FlexWrap, CSSWrapType, 0, 1);
CSSNODE_PROP_ENUM(Overflow, Overflow, CSSOverflow, 0, 2);
CSSNODE_PROP_FLOAT(Flex, Flex);
CSSNODE_PROP_FLOAT(FlexGrow, FlexGrow);
CSSNODE_PROP_FLOAT(FlexShrink, FlexShrink);
CSSNODE_PROP_FLOAT(FlexBasis, FlexBasis);
// CSS_NODE_STYLE_PROPERTY
CSSNODE_PROP_FLOAT(StyleWidth, Width);
CSSNODE_PROP_FLOAT(StyleHeight, Height);
CSSNODE_PROP_FLOAT(StyleMinWidth, MinWidth);
CSSNODE_PROP_FLOAT(StyleMinHeight, MinHeight);
CSSNODE_PROP_FLOAT(StyleMaxWidth, MaxWidth);
CSSNODE_PROP_FLOAT(StyleMaxHeight, MaxHeight);
// CSS_NODE_LAYOUT_PROPERTY
CSSNODE_LAYOUT_PROP(LayoutX, Left);
CSSNODE_LAYOUT_PROP(LayoutY, Top);
CSSNODE_LAYOUT_PROP(LayoutHeight, Height);
CSSNODE_LAYOUT_PROP(LayoutWidth, Width);
CSSNODE_LAYOUT_PROP(LayoutDirection, Direction);
#ifndef CSSLAYOUT_H
#define CSSLAYOUT_H
#include <nan.h>
#include "CSSLayout.h"
#ifndef CSSNODE_GETTER_SETTER
#define CSSNODE_GETTER_SETTER(NAME, PROP) \
Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New(#NAME).ToLocalChecked(), Get##PROP, Set##PROP);
#endif
#ifndef CSSNODE_GETTER
#define CSS_NODE_GETTER(NAME, PROP) \
Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New(#NAME).ToLocalChecked(), Get##PROP);
#endif
#ifndef CSSNODE_ASSERT
#define CSSNODE_ASSERT \
CSSLayoutNode* obj = ObjectWrap::Unwrap<CSSLayoutNode>(info.Holder()); \
if (obj->_node == nullptr) { \
Nan::ThrowReferenceError("CSSLayoutNode has been freed."); \
}
#endif
#ifndef V8BOOLEAN_ASSERT
#define V8BOOLEAN_ASSERT \
if (!value->IsBoolean()) { \
Nan::ThrowTypeError("argument must be a Boolean"); \
}
#endif
#ifndef V8INT32_ASSERT
#define V8INT32_ASSERT \
if (!value->IsInt32()) { \
Nan::ThrowTypeError("argument must be an integer"); \
}
#endif
#ifndef V8NUMBER_ASSERT
#define V8NUMBER_ASSERT \
if (!value->IsNumber()) { \
Nan::ThrowTypeError("argument must be a number"); \
}
#endif
#ifndef V8RANGE_ASSERT
#define V8RANGE_ASSERT(MIN, MAX) \
int32_t iValue = value->Int32Value(); \
if (iValue < MIN || iValue > MAX) { \
Nan::ThrowRangeError("argument out of range"); \
}
#endif
#ifndef CSSNODE_PROPERTY
#define CSSNODE_PROPERTY(PROP) \
static NAN_GETTER(Get##PROP); \
static NAN_SETTER(Set##PROP);
#endif
#ifndef CSSNODE_PROP_BOOL
#define CSSNODE_PROP_BOOL(PROP, NATIVE) \
NAN_GETTER(CSSLayoutNode::Get##PROP) { \
CSSNODE_ASSERT \
info.GetReturnValue().Set(Nan::New(CSSNodeGet##NATIVE(obj->_node))); \
} \
\
NAN_SETTER(CSSLayoutNode::Set##PROP) { \
V8BOOLEAN_ASSERT \
CSSNODE_ASSERT \
bool bValue = value->BooleanValue(); \
CSSNodeSet##NATIVE(obj->_node, bValue); \
}
#endif
#ifndef CSSNODE_PROP_ENUM
#define CSSNODE_PROP_ENUM(PROP, NATIVE, ENUM, MIN, MAX) \
NAN_GETTER(CSSLayoutNode::Get##PROP) { \
CSSNODE_ASSERT \
info.GetReturnValue().Set(Nan::New((int32_t)CSSNodeStyleGet##NATIVE(obj->_node))); \
} \
\
NAN_SETTER(CSSLayoutNode::Set##PROP) { \
V8INT32_ASSERT \
CSSNODE_ASSERT \
V8RANGE_ASSERT(MIN, MAX) \
CSSNodeStyleSet##NATIVE(obj->_node, (ENUM)iValue); \
}
#endif
#ifndef CSSNODE_PROP_FLOAT
#define CSSNODE_PROP_FLOAT(PROP, NATIVE) \
NAN_GETTER(CSSLayoutNode::Get##PROP) { \
CSSNODE_ASSERT \
info.GetReturnValue().Set(Nan::New(CSSNodeStyleGet##NATIVE(obj->_node))); \
} \
\
NAN_SETTER(CSSLayoutNode::Set##PROP) { \
V8NUMBER_ASSERT \
CSSNODE_ASSERT \
float fValue = static_cast<float>(value->NumberValue()); \
CSSNodeStyleSet##NATIVE(obj->_node, fValue); \
}
#endif
#ifndef CSSNODE_LAYOUT_PROP
#define CSSNODE_LAYOUT_PROP(PROP, NATIVE) \
NAN_GETTER(CSSLayoutNode::Get##PROP) { \
CSSNODE_ASSERT \
info.GetReturnValue().Set(Nan::New(CSSNodeLayoutGet##NATIVE(obj->_node))); \
}
#endif
class CSSLayoutNode : public Nan::ObjectWrap {
public:
static void Init(v8::Local<v8::Object> exports);
v8::Persistent<v8::Function> _measure;
v8::Persistent<v8::Function> _print;
private:
explicit CSSLayoutNode(v8::Local<v8::Object> self);
~CSSLayoutNode();
static NAN_METHOD(New);
static NAN_METHOD(Free);
static NAN_METHOD(FreeRecursive);
static NAN_METHOD(ValueIsUndefined);
static NAN_GETTER(GetIsDirty);
static NAN_METHOD(MarkDirty);
static NAN_METHOD(InstanceCount);
// CSS_NODE_PROPERTY
CSSNODE_PROPERTY(IsTextNode);
CSSNODE_PROPERTY(HasNewLayout);
CSSNODE_PROPERTY(MeasureFunction);
//CSSNODE_PROPERTY(PrintFunction);
// CSS_NODE_STYLE_PROPERTY
CSSNODE_PROPERTY(StyleDirection);
CSSNODE_PROPERTY(FlexDirection);
CSSNODE_PROPERTY(JustifyContent);
CSSNODE_PROPERTY(AlignContent);
CSSNODE_PROPERTY(AlignItems);
CSSNODE_PROPERTY(AlignSelf);
CSSNODE_PROPERTY(PositionType);
CSSNODE_PROPERTY(Wrap);
CSSNODE_PROPERTY(Overflow);
CSSNODE_PROPERTY(Flex);
CSSNODE_PROPERTY(FlexGrow);
CSSNODE_PROPERTY(FlexShrink);
CSSNODE_PROPERTY(FlexBasis);
// CSS_NODE_STYLE_EDGE_PROPERTY
// CSS_NODE_STYLE_PROPERTY
CSSNODE_PROPERTY(StyleWidth);
CSSNODE_PROPERTY(StyleHeight);
CSSNODE_PROPERTY(StyleMinWidth);
CSSNODE_PROPERTY(StyleMinHeight);
CSSNODE_PROPERTY(StyleMaxWidth);
CSSNODE_PROPERTY(StyleMaxHeight);
// CSS_NODE_LAYOUT_PROPERTY
static NAN_GETTER(GetLayoutX);
static NAN_GETTER(GetLayoutY);
static NAN_GETTER(GetLayoutHeight);
static NAN_GETTER(GetLayoutWidth);
static NAN_GETTER(GetLayoutDirection);
static Nan::Persistent<v8::Function> constructor;
CSSNodeRef _node;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment