1/*
2 * Copyright 2001-2009, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Pahtz <pahtz@yahoo.com.au>
7 *		Axel Dörfler, axeld@pinc-software.de
8 */
9
10
11/*!	Class for low-overhead port-based messaging */
12
13
14#include <ServerLink.h>
15
16#include <stdlib.h>
17#include <string.h>
18#include <new>
19
20#include <Gradient.h>
21#include <GradientLinear.h>
22#include <GradientRadial.h>
23#include <GradientRadialFocus.h>
24#include <GradientDiamond.h>
25#include <GradientConic.h>
26#include <Region.h>
27#include <Shape.h>
28#include <StackOrHeapArray.h>
29
30#include <ServerProtocol.h>
31
32
33//#define TRACE_SERVER_LINK_GRADIENTS
34#ifdef TRACE_SERVER_LINK_GRADIENTS
35#	include <OS.h>
36#	define GTRACE(x) debug_printf x
37#else
38#	define GTRACE(x) ;
39#endif
40
41
42namespace BPrivate {
43
44
45ServerLink::ServerLink()
46{
47}
48
49
50ServerLink::~ServerLink()
51{
52}
53
54
55void
56ServerLink::SetTo(port_id sender, port_id receiver)
57{
58	fSender->SetPort(sender);
59	fReceiver->SetPort(receiver);
60}
61
62
63status_t
64ServerLink::ReadRegion(BRegion* region)
65{
66	fReceiver->Read(&region->fCount, sizeof(int32));
67	if (region->fCount > 0) {
68		fReceiver->Read(&region->fBounds, sizeof(clipping_rect));
69		if (!region->_SetSize(region->fCount))
70			return B_NO_MEMORY;
71		return fReceiver->Read(region->fData,
72			region->fCount * sizeof(clipping_rect));
73	}
74
75	return fReceiver->Read(&region->fBounds, sizeof(clipping_rect));
76}
77
78
79status_t
80ServerLink::AttachRegion(const BRegion& region)
81{
82	fSender->Attach(&region.fCount, sizeof(int32));
83	if (region.fCount > 0) {
84		fSender->Attach(&region.fBounds, sizeof(clipping_rect));
85		return fSender->Attach(region.fData,
86			region.fCount * sizeof(clipping_rect));
87	}
88
89	return fSender->Attach(&region.fBounds, sizeof(clipping_rect));
90}
91
92
93status_t
94ServerLink::ReadShape(BShape* shape)
95{
96	int32 opCount, ptCount;
97	fReceiver->Read(&opCount, sizeof(int32));
98	fReceiver->Read(&ptCount, sizeof(int32));
99
100	BStackOrHeapArray<uint32, 64> opList(opCount);
101	if (opCount > 0)
102		fReceiver->Read(opList, opCount * sizeof(uint32));
103
104	BStackOrHeapArray<BPoint, 64> ptList(ptCount);
105	if (ptCount > 0)
106		fReceiver->Read(ptList, ptCount * sizeof(BPoint));
107
108	shape->SetData(opCount, ptCount, opList, ptList);
109	return B_OK;
110}
111
112
113status_t
114ServerLink::AttachShape(BShape& shape)
115{
116	int32 opCount, ptCount;
117	uint32* opList;
118	BPoint* ptList;
119
120	shape.GetData(&opCount, &ptCount, &opList, &ptList);
121
122	fSender->Attach(&opCount, sizeof(int32));
123	fSender->Attach(&ptCount, sizeof(int32));
124	if (opCount > 0)
125		fSender->Attach(opList, opCount * sizeof(uint32));
126	if (ptCount > 0)
127		fSender->Attach(ptList, ptCount * sizeof(BPoint));
128	return B_OK;
129}
130
131
132status_t
133ServerLink::ReadGradient(BGradient** _gradient)
134{
135	GTRACE(("ServerLink::ReadGradient\n"));
136	return fReceiver->ReadGradient(_gradient);
137}
138
139
140status_t
141ServerLink::AttachGradient(const BGradient& gradient)
142{
143	GTRACE(("ServerLink::AttachGradient\n"));
144	BGradient::Type gradientType = gradient.GetType();
145	int32 stopCount = gradient.CountColorStops();
146	GTRACE(("ServerLink::AttachGradient> color stop count == %d\n",
147		(int)stopCount));
148	fSender->Attach(&gradientType, sizeof(BGradient::Type));
149	fSender->Attach(&stopCount, sizeof(int32));
150	if (stopCount > 0) {
151		for (int i = 0; i < stopCount; i++) {
152			fSender->Attach(gradient.ColorStopAtFast(i),
153				sizeof(BGradient::ColorStop));
154		}
155	}
156
157	switch (gradientType) {
158		case BGradient::TYPE_LINEAR:
159		{
160			GTRACE(("ServerLink::AttachGradient> type == TYPE_LINEAR\n"));
161			const BGradientLinear* linear = (BGradientLinear*)&gradient;
162			fSender->Attach(linear->Start());
163			fSender->Attach(linear->End());
164			break;
165		}
166		case BGradient::TYPE_RADIAL:
167		{
168			GTRACE(("ServerLink::AttachGradient> type == TYPE_RADIAL\n"));
169			const BGradientRadial* radial = (BGradientRadial*)&gradient;
170			BPoint center = radial->Center();
171			float radius = radial->Radius();
172			fSender->Attach(&center, sizeof(BPoint));
173			fSender->Attach(&radius, sizeof(float));
174			break;
175		}
176		case BGradient::TYPE_RADIAL_FOCUS:
177		{
178			GTRACE(("ServerLink::AttachGradient> type == TYPE_RADIAL_FOCUS\n"));
179			const BGradientRadialFocus* radialFocus
180				= (BGradientRadialFocus*)&gradient;
181			BPoint center = radialFocus->Center();
182			BPoint focal = radialFocus->Focal();
183			float radius = radialFocus->Radius();
184			fSender->Attach(&center, sizeof(BPoint));
185			fSender->Attach(&focal, sizeof(BPoint));
186			fSender->Attach(&radius, sizeof(float));
187			break;
188		}
189		case BGradient::TYPE_DIAMOND:
190		{
191			GTRACE(("ServerLink::AttachGradient> type == TYPE_DIAMOND\n"));
192			const BGradientDiamond* diamond = (BGradientDiamond*)&gradient;
193			BPoint center = diamond->Center();
194			fSender->Attach(&center, sizeof(BPoint));
195			break;
196		}
197		case BGradient::TYPE_CONIC:
198		{
199			GTRACE(("ServerLink::AttachGradient> type == TYPE_CONIC\n"));
200			const BGradientConic* conic = (BGradientConic*)&gradient;
201			BPoint center = conic->Center();
202			float angle = conic->Angle();
203			fSender->Attach(&center, sizeof(BPoint));
204			fSender->Attach(&angle, sizeof(float));
205			break;
206		}
207		case BGradient::TYPE_NONE:
208		{
209			GTRACE(("ServerLink::AttachGradient> type == TYPE_NONE\n"));
210			break;
211		}
212	}
213	return B_OK;
214}
215
216
217status_t
218ServerLink::FlushWithReply(int32& code)
219{
220	status_t status = Flush(B_INFINITE_TIMEOUT, true);
221	if (status < B_OK)
222		return status;
223
224	return GetNextMessage(code);
225}
226
227
228}	// namespace BPrivate
229