xref: /haiku/src/kits/interface/Picture.cpp (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		Picture.cpp
23 //	Author:			Marc Flerackers (mflerackers@androme.be)
24 //	Description:	BPicture records a series of drawing instructions that can
25 //                  be "replayed" later.
26 //------------------------------------------------------------------------------
27 
28 // Standard Includes -----------------------------------------------------------
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 // System Includes -------------------------------------------------------------
34 #include <Picture.h>
35 #include <Message.h>
36 #include <ByteOrder.h>
37 #include <TPicture.h>
38 #include <Errors.h>
39 #include <List.h>
40 #include <AppServerLink.h>
41 #include <PortMessage.h>
42 #include <ServerProtocol.h>
43 
44 // Project Includes ------------------------------------------------------------
45 
46 // Local Includes --------------------------------------------------------------
47 
48 // Local Defines ---------------------------------------------------------------
49 
50 // Globals ---------------------------------------------------------------------
51 
52 struct _BPictureExtent_ {
53 	void	*fNewData;
54 	int32	fNewSize;
55 	void	*fOldData;
56 	int32	fOldSize;
57 	BList	fPictures;	// In R5 this is a BArray<BPicture*> which is completely
58 						// inline.
59 };
60 
61 status_t do_playback(void * data, int32 size, BList& pictures,
62 	void **callBackTable, int32 tableEntries, void *user);
63 
64 //------------------------------------------------------------------------------
65 BPicture::BPicture()
66 	:	token(-1),
67 		extent(NULL),
68 		usurped(NULL)
69 {
70 	extent = new _BPictureExtent_;
71 	extent->fNewData = NULL;
72 	extent->fNewSize = 0;
73 	extent->fOldData = NULL;
74 	extent->fOldSize = 0;
75 }
76 //------------------------------------------------------------------------------
77 BPicture::BPicture(const BPicture &picture)
78 	:	token(-1),
79 		extent(NULL),
80 		usurped(NULL)
81 {
82 	init_data();
83 
84 	if (picture.token != -1)
85 	{
86 
87 		BPrivate::BAppServerLink link;
88 		PortMessage msg;
89 
90 		link.Attach<int32>(AS_CLONE_PICTURE);
91 		link.Attach<int32>(picture.token);
92 		link.FlushWithReply(&msg);
93 		msg.Read<int32>(&token);
94 
95 	}
96 	if (picture.extent->fNewData != NULL)
97 	{
98 		extent->fNewSize = picture.extent->fNewSize;
99 		extent->fNewData = malloc(extent->fNewSize);
100 		memcpy(extent->fNewData, picture.extent->fNewData, extent->fNewSize);
101 
102 		BPicture *pic;
103 
104 		for (int32 i = 0; i < picture.extent->fPictures.CountItems(); i++)
105 		{
106 			pic = new BPicture(*(BPicture*)picture.extent->fPictures.ItemAt(i));
107 			extent->fPictures.AddItem(pic);
108 		}
109 	}
110 	else if (picture.extent->fOldData != NULL)
111 	{
112 		extent->fOldSize = picture.extent->fOldSize;
113 		extent->fOldData = malloc(extent->fOldSize);
114 		memcpy(extent->fOldData, picture.extent->fOldData, extent->fOldSize);
115 
116 		// In old data the sub pictures are inside the data
117 	}
118 }
119 //------------------------------------------------------------------------------
120 BPicture::BPicture(BMessage *archive)
121 	:	token(-1),
122 		extent(NULL),
123 		usurped(NULL)
124 {
125 	init_data();
126 
127 	int32 version, size;
128 	int8 endian;
129 	const void *data;
130 
131 	if (archive->FindInt32("_ver", &version) != B_OK)
132 		version = 0;
133 
134 	if (archive->FindInt8("_endian", &endian) != B_OK)
135 		endian = 0;
136 
137 	if (archive->FindData("_data", B_RAW_TYPE, &data, (ssize_t*)&size) != B_OK)
138 		return;
139 
140 	// Load sub pictures
141 	BMessage picMsg;
142 	int32 i = 0;
143 
144 	while (archive->FindMessage("piclib", i++, &picMsg) == B_OK)
145 	{
146 		BPicture *pic = new BPicture(&picMsg);
147 		extent->fPictures.AddItem(pic);
148 	}
149 
150 	if (version == 0)
151 		import_old_data(data, size);
152 	else if (version == 1)
153 	{
154 		extent->fNewSize = size;
155 		extent->fNewData = malloc(extent->fNewSize);
156 		memcpy(extent->fNewData, data, extent->fNewSize);
157 
158 //		swap_data(extent->fNewData, extent->fNewSize);
159 
160 		if (extent->fNewSize != 0 && extent->fNewData != 0)
161 		{
162 			BPrivate::BAppServerLink link;
163 		PortMessage msg;
164 			BPicture *pic;
165 
166 			link.Attach<int32>(AS_CREATE_PICTURE);
167 			link.Attach<int32>(extent->fPictures.CountItems());
168 			for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
169 			{
170 				pic=(BPicture*)extent->fPictures.ItemAt(i);
171 				if(pic)
172 					link.Attach<int32>(pic->token);
173 			}
174 			link.Attach<int32>(extent->fNewSize);
175 			link.Attach(extent->fNewData,extent->fNewSize);
176 			link.FlushWithReply(&msg);
177 			msg.Read<int32>(&token);
178 		}
179 	}
180 
181 	// Do we just free the data now?
182 	if (extent->fNewData)
183 	{
184 		free(extent->fNewData);
185 		extent->fNewData = NULL;
186 		extent->fNewSize = 0;
187 	}
188 
189 	if (extent->fOldData)
190 	{
191 		free(extent->fOldData);
192 		extent->fOldData = NULL;
193 		extent->fOldSize = 0;
194 	}
195 
196 	// What with the sub pictures?
197 	for (i = 0; i < extent->fPictures.CountItems(); i++)
198 		delete (BPicture *)extent->fPictures.ItemAt(i);
199 	extent->fPictures.MakeEmpty();
200 }
201 //------------------------------------------------------------------------------
202 BPicture::~BPicture()
203 {
204 	if (token != -1)
205 	{
206 		BPrivate::BAppServerLink link;
207 
208 		link.Attach<int32>(AS_DELETE_PICTURE);
209 		link.Attach<int32>(token);
210 		link.Flush();
211 	}
212 
213 	if (extent->fNewData != NULL)
214 	{
215 		free(extent->fNewData);
216 		extent->fNewData = NULL;
217 		extent->fNewSize = 0;
218 	}
219 
220 	if (extent->fOldData != NULL)
221 	{
222 		free(extent->fOldData);
223 		extent->fOldData = NULL;
224 		extent->fOldSize = 0;
225 	}
226 
227 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
228 		delete (BPicture *)extent->fPictures.ItemAt(i);
229 	extent->fPictures.MakeEmpty();
230 
231 	free(extent);
232 }
233 //------------------------------------------------------------------------------
234 BArchivable *BPicture::Instantiate(BMessage *archive)
235 {
236 	if (validate_instantiation(archive, "BPicture"))
237 		return new BPicture(archive);
238 	else
239 		return NULL;
240 }
241 //------------------------------------------------------------------------------
242 status_t BPicture::Archive(BMessage *archive, bool deep) const
243 {
244 	if (!const_cast<BPicture*>(this)->assert_local_copy())
245 		return B_ERROR;
246 
247 	status_t err = BArchivable::Archive(archive, deep);
248 
249 	if (err != B_OK)
250 		return err;
251 
252 	err = archive->AddInt32("_ver", 1);
253 
254 	if (err != B_OK)
255 		return err;
256 
257 	err = archive->AddInt8("_endian", B_HOST_IS_BENDIAN);
258 
259 	if (err != B_OK)
260 		return err;
261 
262 	err = archive->AddData("_data", B_RAW_TYPE, extent->fNewData,
263 		extent->fNewSize);
264 
265 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
266 	{
267 		BMessage picMsg;
268 
269 		((BPicture*)extent->fPictures.ItemAt(i))->Archive(&picMsg, deep);
270 
271 		archive->AddMessage("piclib", &picMsg);
272 	}
273 
274 	return err;
275 }
276 //------------------------------------------------------------------------------
277 status_t BPicture::Perform(perform_code d, void *arg)
278 {
279 	return BArchivable::Perform(d, arg);
280 }
281 //------------------------------------------------------------------------------
282 status_t BPicture::Play(void **callBackTable, int32 tableEntries, void *user)
283 {
284 	if (!assert_local_copy())
285 		return B_ERROR;
286 
287 	return do_playback(extent->fNewData, extent->fNewSize, extent->fPictures,
288 		callBackTable, tableEntries, user);
289 }
290 //------------------------------------------------------------------------------
291 status_t BPicture::Flatten(BDataIO *stream)
292 {
293 	if (!assert_local_copy())
294 		return B_ERROR;
295 
296 	// TODO check the header
297 	int32 bla1 = 2;
298 	int32 bla2 = 0;
299 	int32 count = 0;
300 
301 	stream->Write(&bla1, 4);
302 	stream->Write(&bla2, 4);
303 
304 	count = extent->fPictures.CountItems();
305 	stream->Write(&count, 4);
306 
307 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
308 		((BPicture*)extent->fPictures.ItemAt(i))->Flatten(stream);
309 
310 	stream->Write(&extent->fNewSize, 4);
311 	stream->Write(extent->fNewData, extent->fNewSize);
312 
313 	return B_OK;
314 }
315 //------------------------------------------------------------------------------
316 status_t BPicture::Unflatten(BDataIO *stream)
317 {
318 	// TODO check the header
319 	int32 bla1 = 2;
320 	int32 bla2 = 0;
321 	int32 count = 0;
322 
323 	stream->Read(&bla1, 4);
324 	stream->Read(&bla2, 4);
325 
326 	stream->Read(&count, 4);
327 
328 	for (int32 i = 0; i < count; i++)
329 	{
330 		BPicture *pic = new BPicture;
331 
332 		pic->Unflatten(stream);
333 
334 		extent->fPictures.AddItem(pic);
335 	}
336 
337 	stream->Read(&extent->fNewSize, 4);
338 	extent->fNewData = malloc(extent->fNewSize);
339 	stream->Read(extent->fNewData, extent->fNewSize);
340 
341 //	swap_data(extent->fNewData, extent->fNewSize);
342 
343 	BPrivate::BAppServerLink link;
344 	PortMessage msg;
345 	BPicture *pic;
346 
347 	link.Attach<int32>(AS_CREATE_PICTURE);
348 	link.Attach<int32>(extent->fPictures.CountItems());
349 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
350 	{
351 		pic=(BPicture*)extent->fPictures.ItemAt(i);
352 		if(pic)
353 			link.Attach<int32>(pic->token);
354 	}
355 	link.Attach<int32>(extent->fNewSize);
356 	link.Attach(extent->fNewData, extent->fNewSize);
357 	link.FlushWithReply(&msg);
358 	msg.Read<int32>(&token);
359 
360 	if (extent->fNewData)
361 	{
362 		free(extent->fNewData);
363 		extent->fNewData = NULL;
364 		extent->fNewSize = 0;
365 	}
366 
367 	return B_OK;
368 }
369 //------------------------------------------------------------------------------
370 void BPicture::_ReservedPicture1() {}
371 void BPicture::_ReservedPicture2() {}
372 void BPicture::_ReservedPicture3() {}
373 //------------------------------------------------------------------------------
374 BPicture &BPicture::operator=(const BPicture &)
375 {
376 	return *this;
377 }
378 //------------------------------------------------------------------------------
379 void BPicture::init_data()
380 {
381 	token = -1;
382 	usurped = NULL;
383 
384 	extent = new _BPictureExtent_;
385 	extent->fNewData = NULL;
386 	extent->fNewSize = 0;
387 	extent->fOldData = NULL;
388 	extent->fOldSize = 0;
389 }
390 //------------------------------------------------------------------------------
391 void BPicture::import_data(const void *data, int32 size, BPicture **subs,
392 						   int32 subCount)
393 {
394 	if (data == NULL || size == 0)
395 		return;
396 
397 	BPrivate::BAppServerLink link;
398 	PortMessage msg;
399 
400 	link.Attach<int32>(AS_CREATE_PICTURE);
401 	link.Attach<int32>(subCount);
402 
403 	for (int32 i = 0; i < subCount; i++)
404 		link.Attach<int32>(subs[i]->token);
405 
406 	link.Attach<int32>(size);
407 	link.Attach(data, size);
408 	link.FlushWithReply(&msg);
409 	msg.Read<int32>(&token);
410 }
411 //------------------------------------------------------------------------------
412 void BPicture::import_old_data(const void *data, int32 size)
413 {
414 	// TODO: do we need to support old data, what is old data?
415 	/*if (data == NULL)
416 		return;
417 
418 	if (size == 0)
419 		return;
420 
421 	convert_old_to_new(data, size, &extent->fNewData, &extent->fNewSize);
422 
423 	BPrivate::BAppServerLink link;
424 	link.Attach<int32>(AS_CREATE_PICTURE);
425 	link.Attach<int32>(0L);
426 	link.Attach<int32>(extent->fNewSize);
427 	link.Attach(extent->fNewData,extent->fNewSize);
428 	link.FlushWithReply(&msg);
429 	msg.Read<int32>(&token)
430 
431 	// Do we free all data now?
432 	free(extent->fNewData);
433 	extent->fNewData = 0;
434 	extent->fNewSize = 0;
435 	free(extent->fOldData);
436 	extent->fOldData = 0;
437 	extent->fOldSize = 0;*/
438 }
439 //------------------------------------------------------------------------------
440 void BPicture::set_token(int32 _token)
441 {
442 	token = _token;
443 }
444 //------------------------------------------------------------------------------
445 bool BPicture::assert_local_copy()
446 {
447 	if (extent->fNewData != NULL)
448 		return true;
449 
450 	if (token == -1)
451 		return false;
452 
453 /*	BPrivate::BAppServerLink link;
454 	int32 count;
455 
456 	link.Attach<int32>(AS_DOWNLOAD_PICTURE);
457 	link.Attach<int32>(token);
458 	link.FlushWithReply(&msg);
459 	count=*((int32*)replydata.buffer);
460 
461 	// Read sub picture tokens
462 	for (int32 i = 0; i < count; i++)
463 	{
464 		BPicture *pic = new BPicture;
465 
466 		link.sread(4, &pic->token);
467 
468 		extent->fPictures.AddItem(pic);
469 	}
470 
471 	link.sread(4, &extent->fNewSize);
472 	extent->fNewData = malloc(extent->fNewSize);
473 	link.sread(extent->fNewSize, &extent->fNewData);*/
474 
475 	return true;
476 }
477 //------------------------------------------------------------------------------
478 bool BPicture::assert_old_local_copy()
479 {
480 	if (extent->fOldData != NULL)
481 		return true;
482 
483 	if (!assert_local_copy())
484 		return false;
485 
486 //	convert_new_to_old(extent->fNewData, extent->fNewSize, extent->fOldData,
487 //		extent->fOldSize);
488 
489 	return true;
490 }
491 //------------------------------------------------------------------------------
492 bool BPicture::assert_server_copy()
493 {
494 	if (token != -1)
495 		return true;
496 
497 	if (extent->fNewData == NULL)
498 		return false;
499 
500 /*	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
501 		extent->fPictures.ItemAt(i)->assert_server_copy();
502 
503 	BPrivate::BAppServerLink link;
504 	link.Attach<int32>(AS_CREATE_PICTURE);
505 	link.Attach<int32>(extent->fPictures.CountItems());
506 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
507 		link.Attach<int32>(extent->fPictures.ItemAt(i)->token);
508 	link.Attach<int32>(extent->fNewSize);
509 	link.Attach(extent->fNewData,extent->fNewSize);
510 	link.FlushWithReply(&msg);
511 	msg.Read<int32>(&token);
512 
513 	return token != -1;*/
514 	return true;
515 }
516 //------------------------------------------------------------------------------
517 BPicture::BPicture(const void *data, int32 size)
518 {
519 	init_data();
520 	import_old_data(data, size);
521 }
522 //------------------------------------------------------------------------------
523 const void *BPicture::Data() const
524 {
525 	if (extent->fNewData == NULL)
526 	{
527 		const_cast<BPicture*>(this)->assert_local_copy();
528 		//convert_new_to_old(void *, long, void **, long *);
529 	}
530 
531 	return extent->fNewData;
532 }
533 //------------------------------------------------------------------------------
534 int32 BPicture::DataSize() const
535 {
536 	if (extent->fNewData == NULL)
537 	{
538 		const_cast<BPicture*>(this)->assert_local_copy();
539 		//convert_new_to_old(void *, long, void **, long *);
540 	}
541 
542 	return extent->fNewSize;
543 }
544 //------------------------------------------------------------------------------
545 void BPicture::usurp(BPicture *lameDuck)
546 {
547 	if (token != -1)
548 	{
549 		BPrivate::BAppServerLink link;
550 
551 		link.Attach<int32>(AS_DELETE_PICTURE);
552 		link.Attach<int32>(token);
553 		link.Flush();
554 	}
555 
556 	if (extent->fNewData != NULL)
557 	{
558 		free(extent->fNewData);
559 		extent->fNewData = NULL;
560 		extent->fNewSize = 0;
561 	}
562 
563 	if (extent->fOldData != NULL)
564 	{
565 		free(extent->fOldData);
566 		extent->fOldData = NULL;
567 		extent->fOldSize = 0;
568 	}
569 
570 	for (int32 i = 0; i < extent->fPictures.CountItems(); i++)
571 		delete (BPicture *)extent->fPictures.ItemAt(i);
572 	extent->fPictures.MakeEmpty();
573 
574 	free(extent);
575 
576 	init_data();
577 
578 	// Do the usurping
579 	usurped = lameDuck;
580 }
581 //------------------------------------------------------------------------------
582 BPicture *BPicture::step_down()
583 {
584 	BPicture *lameDuck = usurped;
585 
586 	usurped = NULL;
587 
588 	return lameDuck;
589 }
590 //------------------------------------------------------------------------------
591 status_t do_playback(void * data, int32 size, BList& pictures,
592 	void **callBackTable, int32 tableEntries, void *user)
593 {
594 	TPicture pic(data, size, pictures);
595 
596 	return pic.Play(callBackTable, tableEntries, user);
597 }
598 //------------------------------------------------------------------------------
599 
600 
601