Marker for measure callbacks

Summary:
@public

Wraps measure callbacks with a marker.

Reviewed By: SidharthGuglani

Differential Revision: D13896745

fbshipit-source-id: d6e14fe93f666b06516be1aef7f8e1bfe45440a7
This commit is contained in:
David Aurelio
2019-02-01 03:31:12 -08:00
committed by Facebook Github Bot
parent 719fa3cca3
commit 0d026bd1a0
4 changed files with 66 additions and 12 deletions

View File

@@ -197,6 +197,20 @@ TEST_F(MarkerTest, layout_marker_has_max_measure_cache) {
(YGMarkerLayoutData{.layouts = 3, .measures = 3, .maxMeasureCache = 7})); (YGMarkerLayoutData{.layouts = 3, .measures = 3, .maxMeasureCache = 7}));
} }
TEST_F(MarkerTest, measure_functions_get_wrapped) {
auto root = makeNode();
YGNodeSetMeasureFunc(
root.get(), [](YGNodeRef, float, YGMeasureMode, float, YGMeasureMode) {
return YGSize{};
});
calculateLayout(root);
auto& markerCookie = findLastMarker(YGMarkerMeasure);
ASSERT_EQ(markerCookie.start.marker, YGMarkerMeasure)
<< "have " << markerCookies.size() << " recorded markers";
}
void* MarkerTest::startMarker( void* MarkerTest::startMarker(
YGMarker marker, YGMarker marker,
YGNodeRef node, YGNodeRef node,
@@ -218,6 +232,8 @@ void MarkerTest::endMarker(
case YGMarkerLayout: case YGMarkerLayout:
cookie->end.markerData.layout = *marker::data<YGMarkerLayout>(data); cookie->end.markerData.layout = *marker::data<YGMarkerLayout>(data);
break; break;
case YGMarkerMeasure:
break;
}; };
} }
@@ -245,6 +261,8 @@ const char* markerTypeName(YGMarker type) {
switch (type) { switch (type) {
case YGMarkerLayout: case YGMarkerLayout:
return "YGMarkerLayout"; return "YGMarkerLayout";
case YGMarkerMeasure:
return "YGMarkerMeasure";
} }
} }

View File

@@ -15,6 +15,7 @@ typedef struct YGConfig* YGConfigRef;
typedef YG_ENUM_BEGIN(YGMarker){ typedef YG_ENUM_BEGIN(YGMarker){
YGMarkerLayout, YGMarkerLayout,
YGMarkerMeasure,
} YG_ENUM_END(YGMarker); } YG_ENUM_END(YGMarker);
typedef struct { typedef struct {
@@ -25,8 +26,13 @@ typedef struct {
int cachedMeasures; int cachedMeasures;
} YGMarkerLayoutData; } YGMarkerLayoutData;
typedef struct {
bool _unused;
} YGMarkerNoData;
typedef union { typedef union {
YGMarkerLayoutData* layout; YGMarkerLayoutData* layout;
YGMarkerNoData* noData;
} YGMarkerData; } YGMarkerData;
typedef struct { typedef struct {
@@ -55,16 +61,24 @@ struct MarkerData;
template <> template <>
struct MarkerData<YGMarkerLayout> { struct MarkerData<YGMarkerLayout> {
using type = YGMarkerLayoutData; using type = YGMarkerLayoutData;
static type*& get(YGMarkerData& d) {
return d.layout;
}
};
template <>
struct MarkerData<YGMarkerMeasure> {
using type = YGMarkerNoData;
static type*& get(YGMarkerData& d) {
return d.noData;
}
}; };
} // namespace detail } // namespace detail
template <YGMarker M> template <YGMarker M>
typename detail::MarkerData<M>::type* data(YGMarkerData) = delete; typename detail::MarkerData<M>::type* data(YGMarkerData d) {
return detail::MarkerData<M>::get(d);
template <>
inline YGMarkerLayoutData* data<YGMarkerLayout>(YGMarkerData d) {
return d.layout;
} }
} // namespace marker } // namespace marker

View File

@@ -1688,8 +1688,14 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(
YGDimensionHeight); YGDimensionHeight);
} else { } else {
// Measure the text under the current constraints. // Measure the text under the current constraints.
const YGSize measuredSize = node->getMeasure()( const YGSize measuredSize = marker::MarkerSection<YGMarkerMeasure>::wrap(
node, innerWidth, widthMeasureMode, innerHeight, heightMeasureMode); node,
node->getMeasure(),
node,
innerWidth,
widthMeasureMode,
innerHeight,
heightMeasureMode);
node->setLayoutMeasuredDimension( node->setLayoutMeasuredDimension(
YGNodeBoundAxis( YGNodeBoundAxis(

View File

@@ -14,15 +14,24 @@ namespace marker {
template <YGMarker MarkerType> template <YGMarker MarkerType>
class MarkerSection { class MarkerSection {
private:
using Data = detail::MarkerData<MarkerType>;
public: public:
MarkerSection(YGNodeRef node) : MarkerSection{node, node->getConfig()} {} MarkerSection(YGNodeRef node) : MarkerSection{node, node->getConfig()} {}
~MarkerSection() { ~MarkerSection() {
if (endMarker_) { if (endMarker_) {
endMarker_(MarkerType, node_, {&data}, userData_); endMarker_(MarkerType, node_, markerData(&data), userData_);
} }
} }
typename detail::MarkerData<MarkerType>::type data = {}; typename Data::type data = {};
template <typename Ret, typename... Args>
static Ret wrap(YGNodeRef node, Ret (*fn)(Args...), Args... args) {
MarkerSection<MarkerType> section{node};
return fn(std::forward<Args>(args)...);
}
private: private:
decltype(YGMarkerCallbacks{}.endMarker) endMarker_; decltype(YGMarkerCallbacks{}.endMarker) endMarker_;
@@ -34,9 +43,16 @@ private:
MarkerSection(YGNodeRef node, YGMarkerCallbacks* callbacks) MarkerSection(YGNodeRef node, YGMarkerCallbacks* callbacks)
: endMarker_{callbacks ? callbacks->endMarker : nullptr}, : endMarker_{callbacks ? callbacks->endMarker : nullptr},
node_{node}, node_{node},
userData_{callbacks && callbacks->startMarker userData_{
? callbacks->startMarker(MarkerType, node, {&data}) callbacks && callbacks->startMarker
: nullptr} {} ? callbacks->startMarker(MarkerType, node, markerData(&data))
: nullptr} {}
static YGMarkerData markerData(typename Data::type* d) {
YGMarkerData markerData = {};
Data::get(markerData) = d;
return markerData;
}
}; };
} // namespace marker } // namespace marker