• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkStackViewLayout.h"
2 
SkStackViewLayout()3 SkStackViewLayout::SkStackViewLayout()
4 {
5 	fMargin.set(0, 0, 0, 0);
6 	fSpacer	= 0;
7 	fOrient	= kHorizontal_Orient;
8 	fPack	= kStart_Pack;
9 	fAlign	= kStart_Align;
10 	fRound	= false;
11 }
12 
setOrient(Orient ori)13 void SkStackViewLayout::setOrient(Orient ori)
14 {
15 	SkASSERT((unsigned)ori < kOrientCount);
16 	fOrient = SkToU8(ori);
17 }
18 
getMargin(SkRect * margin) const19 void SkStackViewLayout::getMargin(SkRect* margin) const
20 {
21 	if (margin)
22 		*margin = fMargin;
23 }
24 
setMargin(const SkRect & margin)25 void SkStackViewLayout::setMargin(const SkRect& margin)
26 {
27 	fMargin = margin;
28 }
29 
setSpacer(SkScalar spacer)30 void SkStackViewLayout::setSpacer(SkScalar spacer)
31 {
32 	fSpacer = spacer;
33 }
34 
setPack(Pack pack)35 void SkStackViewLayout::setPack(Pack pack)
36 {
37 	SkASSERT((unsigned)pack < kPackCount);
38 	fPack = SkToU8(pack);
39 }
40 
setAlign(Align align)41 void SkStackViewLayout::setAlign(Align align)
42 {
43 	SkASSERT((unsigned)align < kAlignCount);
44 	fAlign = SkToU8(align);
45 }
46 
setRound(bool r)47 void SkStackViewLayout::setRound(bool r)
48 {
49 	fRound = SkToU8(r);
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 
54 typedef SkScalar (*AlignProc)(SkScalar childLimit, SkScalar parentLimit);
55 typedef SkScalar (SkView::*GetSizeProc)() const;
56 typedef void (SkView::*SetLocProc)(SkScalar coord);
57 typedef void (SkView::*SetSizeProc)(SkScalar coord);
58 
left_align_proc(SkScalar childLimit,SkScalar parentLimit)59 static SkScalar left_align_proc(SkScalar childLimit, SkScalar parentLimit) { return 0; }
center_align_proc(SkScalar childLimit,SkScalar parentLimit)60 static SkScalar center_align_proc(SkScalar childLimit, SkScalar parentLimit) { return SkScalarHalf(parentLimit - childLimit); }
right_align_proc(SkScalar childLimit,SkScalar parentLimit)61 static SkScalar right_align_proc(SkScalar childLimit, SkScalar parentLimit) { return parentLimit - childLimit; }
fill_align_proc(SkScalar childLimit,SkScalar parentLimit)62 static SkScalar fill_align_proc(SkScalar childLimit, SkScalar parentLimit) { return 0; }
63 
64 /*	Measure the main-dimension for all the children. If a child is marked flex in that direction
65 	ignore its current value but increment the counter for flexChildren
66 */
compute_children_limit(SkView * parent,GetSizeProc sizeProc,int * count,uint32_t flexMask,int * flexCount)67 static SkScalar compute_children_limit(SkView* parent, GetSizeProc sizeProc, int* count,
68 									   uint32_t flexMask, int* flexCount)
69 {
70 	SkView::B2FIter	iter(parent);
71 	SkView*			child;
72 	SkScalar		limit = 0;
73 	int				n = 0, flex = 0;
74 
75 	while ((child = iter.next()) != NULL)
76 	{
77 		n += 1;
78 		if (child->getFlags() & flexMask)
79 			flex += 1;
80 		else
81 			limit += (child->*sizeProc)();
82 	}
83 	if (count)
84 		*count = n;
85 	if (flexCount)
86 		*flexCount = flex;
87 	return limit;
88 }
89 
onLayoutChildren(SkView * parent)90 void SkStackViewLayout::onLayoutChildren(SkView* parent)
91 {
92 	static AlignProc gAlignProcs[] = {
93 		left_align_proc,
94 		center_align_proc,
95 		right_align_proc,
96 		fill_align_proc
97 	};
98 
99 	SkScalar			startM, endM, crossStartM, crossLimit;
100 	GetSizeProc			mainGetSizeP, crossGetSizeP;
101 	SetLocProc			mainLocP, crossLocP;
102 	SetSizeProc			mainSetSizeP, crossSetSizeP;
103 	SkView::Flag_Mask	flexMask;
104 
105 	if (fOrient == kHorizontal_Orient)
106 	{
107 		startM		= fMargin.fLeft;
108 		endM		= fMargin.fRight;
109 		crossStartM	= fMargin.fTop;
110 		crossLimit	= -fMargin.fTop - fMargin.fBottom;
111 
112 		mainGetSizeP	= &SkView::width;
113 		crossGetSizeP	= &SkView::height;
114 		mainLocP	= &SkView::setLocX;
115 		crossLocP	= &SkView::setLocY;
116 
117 		mainSetSizeP  = &SkView::setWidth;
118 		crossSetSizeP = &SkView::setHeight;
119 
120 		flexMask	= SkView::kFlexH_Mask;
121 	}
122 	else
123 	{
124 		startM		= fMargin.fTop;
125 		endM		= fMargin.fBottom;
126 		crossStartM	= fMargin.fLeft;
127 		crossLimit	= -fMargin.fLeft - fMargin.fRight;
128 
129 		mainGetSizeP	= &SkView::height;
130 		crossGetSizeP	= &SkView::width;
131 		mainLocP	= &SkView::setLocY;
132 		crossLocP	= &SkView::setLocX;
133 
134 		mainSetSizeP  = &SkView::setHeight;
135 		crossSetSizeP = &SkView::setWidth;
136 
137 		flexMask	= SkView::kFlexV_Mask;
138 	}
139 	crossLimit += (parent->*crossGetSizeP)();
140 	if (fAlign != kStretch_Align)
141 		crossSetSizeP = NULL;
142 
143 	int			childCount, flexCount;
144 	SkScalar	childLimit = compute_children_limit(parent, mainGetSizeP, &childCount, flexMask, &flexCount);
145 
146 	if (childCount == 0)
147 		return;
148 
149 	childLimit += (childCount - 1) * fSpacer;
150 
151 	SkScalar		parentLimit = (parent->*mainGetSizeP)() - startM - endM;
152 	SkScalar		pos = startM + gAlignProcs[fPack](childLimit, parentLimit);
153 	SkScalar		flexAmount = 0;
154 	SkView::B2FIter	iter(parent);
155 	SkView*			child;
156 
157 	if (flexCount > 0 && parentLimit > childLimit)
158 		flexAmount = (parentLimit - childLimit) / flexCount;
159 
160 	while ((child = iter.next()) != NULL)
161 	{
162 		if (fRound)
163 			pos = SkIntToScalar(SkScalarRound(pos));
164 		(child->*mainLocP)(pos);
165 		SkScalar crossLoc = crossStartM + gAlignProcs[fAlign]((child->*crossGetSizeP)(), crossLimit);
166 		if (fRound)
167 			crossLoc = SkIntToScalar(SkScalarRound(crossLoc));
168 		(child->*crossLocP)(crossLoc);
169 
170 		if (crossSetSizeP)
171 			(child->*crossSetSizeP)(crossLimit);
172 		if (child->getFlags() & flexMask)
173 			(child->*mainSetSizeP)(flexAmount);
174 		pos += (child->*mainGetSizeP)() + fSpacer;
175 	}
176 }
177 
178 //////////////////////////////////////////////////////////////////////////////////////
179 
180 #ifdef SK_DEBUG
assert_no_attr(const SkDOM & dom,const SkDOM::Node * node,const char attr[])181 	static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
182 	{
183 		const char* value = dom.findAttr(node, attr);
184 		if (value)
185 			SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
186 	}
187 #else
188 	#define assert_no_attr(dom, node, attr)
189 #endif
190 
onInflate(const SkDOM & dom,const SkDOM::Node * node)191 void SkStackViewLayout::onInflate(const SkDOM& dom, const SkDOM::Node* node)
192 {
193 	int			index;
194 	SkScalar	value[4];
195 
196 	if ((index = dom.findList(node, "orient", "horizontal,vertical")) >= 0)
197 		this->setOrient((Orient)index);
198 	else
199 		assert_no_attr(dom, node, "orient");
200 
201 	if (dom.findScalars(node, "margin", value, 4))
202 	{
203 		SkRect	margin;
204 		margin.set(value[0], value[1], value[2], value[3]);
205 		this->setMargin(margin);
206 	}
207 	else
208 		assert_no_attr(dom, node, "margin");
209 
210 	if (dom.findScalar(node, "spacer", value))
211 		this->setSpacer(value[0]);
212 	else
213 		assert_no_attr(dom, node, "spacer");
214 
215 	if ((index = dom.findList(node, "pack", "start,center,end")) >= 0)
216 		this->setPack((Pack)index);
217 	else
218 		assert_no_attr(dom, node, "pack");
219 
220 	if ((index = dom.findList(node, "align", "start,center,end,stretch")) >= 0)
221 		this->setAlign((Align)index);
222 	else
223 		assert_no_attr(dom, node, "align");
224 }
225 
226 ///////////////////////////////////////////////////////////////////////////////////////////
227 
SkFillViewLayout()228 SkFillViewLayout::SkFillViewLayout()
229 {
230 	fMargin.setEmpty();
231 }
232 
getMargin(SkRect * r) const233 void SkFillViewLayout::getMargin(SkRect* r) const
234 {
235 	if (r)
236 		*r = fMargin;
237 }
238 
setMargin(const SkRect & margin)239 void SkFillViewLayout::setMargin(const SkRect& margin)
240 {
241 	fMargin = margin;
242 }
243 
onLayoutChildren(SkView * parent)244 void SkFillViewLayout::onLayoutChildren(SkView* parent)
245 {
246 	SkView::B2FIter	iter(parent);
247 	SkView*			child;
248 
249 	while ((child = iter.next()) != NULL)
250 	{
251 		child->setLoc(fMargin.fLeft, fMargin.fTop);
252 		child->setSize(	parent->width() - fMargin.fRight - fMargin.fLeft,
253 						parent->height() - fMargin.fBottom - fMargin.fTop);
254 	}
255 }
256 
onInflate(const SkDOM & dom,const SkDOM::Node * node)257 void SkFillViewLayout::onInflate(const SkDOM& dom, const SkDOM::Node* node)
258 {
259 	this->INHERITED::onInflate(dom, node);
260 	(void)dom.findScalars(node, "margin", (SkScalar*)&fMargin, 4);
261 }
262 
263