xref: /haiku/src/servers/app/ServerPicture.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
1 /*
2  * Copyright 2001-2007, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Marc Flerackers (mflerackers@androme.be)
7  *		Stefano Ceccherini (burton666@libero.it)
8  *		Marcus Overhagen <marcus@overhagen.de>
9  */
10 
11 
12 #include "DrawingEngine.h"
13 #include "ServerBitmap.h"
14 #include "ServerPicture.h"
15 #include "ServerTokenSpace.h"
16 #include "ViewLayer.h"
17 #include "WindowLayer.h"
18 
19 #include <LinkReceiver.h>
20 #include <PicturePlayer.h>
21 #include <PictureProtocol.h>
22 #include <ServerProtocol.h>
23 #include <ShapePrivate.h>
24 
25 #include <Bitmap.h>
26 #include <Shape.h>
27 
28 #include <stdio.h>
29 #include <stack>
30 
31 using std::stack;
32 
33 class ShapePainter : public BShapeIterator {
34 	public:
35 		ShapePainter();
36 		virtual ~ShapePainter();
37 
38 		status_t Iterate(const BShape *shape);
39 
40 		virtual status_t IterateMoveTo(BPoint *point);
41 		virtual status_t IterateLineTo(int32 lineCount, BPoint *linePts);
42 		virtual status_t IterateBezierTo(int32 bezierCount, BPoint *bezierPts);
43 		virtual status_t IterateClose();
44 
45 		void Draw(ViewLayer *view, BRect frame, bool filled);
46 
47 	private:
48 		stack<uint32> fOpStack;
49 		stack<BPoint> fPtStack;
50 };
51 
52 ShapePainter::ShapePainter()
53 	:	BShapeIterator()
54 {
55 }
56 
57 ShapePainter::~ShapePainter()
58 {
59 }
60 
61 status_t
62 ShapePainter::Iterate(const BShape *shape)
63 {
64 	// this class doesn't modify the shape data
65 	return BShapeIterator::Iterate(const_cast<BShape *>(shape));
66 }
67 
68 status_t
69 ShapePainter::IterateMoveTo(BPoint *point)
70 {
71 	fOpStack.push(OP_MOVETO);
72 	fPtStack.push(*point);
73 
74 	return B_OK;
75 }
76 
77 status_t
78 ShapePainter::IterateLineTo(int32 lineCount, BPoint *linePts)
79 {
80 	fOpStack.push(OP_LINETO | lineCount);
81 	for(int32 i = 0;i < lineCount;i++)
82 		fPtStack.push(linePts[i]);
83 
84 	return B_OK;
85 }
86 
87 status_t
88 ShapePainter::IterateBezierTo(int32 bezierCount, BPoint *bezierPts)
89 {
90 	bezierCount *= 3;
91 	fOpStack.push(OP_BEZIERTO | bezierCount);
92 	for(int32 i = 0;i < bezierCount;i++)
93 		fPtStack.push(bezierPts[i]);
94 
95 	return B_OK;
96 }
97 
98 status_t
99 ShapePainter::IterateClose(void)
100 {
101 	fOpStack.push(OP_CLOSE);
102 
103 	return B_OK;
104 }
105 
106 void
107 ShapePainter::Draw(ViewLayer *view, BRect frame, bool filled)
108 {
109 	// We're going to draw the currently iterated picture.
110 	int32 opCount, ptCount;
111 	opCount = fOpStack.size();
112 	ptCount = fPtStack.size();
113 
114 	uint32 *opList;
115 	BPoint *ptList;
116 	if(opCount > 0 && ptCount > 0) {
117 		int32 i;
118 		opList = new uint32[opCount];
119 		ptList = new BPoint[ptCount];
120 
121 		for(i = (opCount - 1);i >= 0;i--) {
122 			opList[i] = fOpStack.top();
123 			fOpStack.pop();
124 		}
125 
126 		for(i = (ptCount - 1);i >= 0;i--) {
127 			ptList[i] = fPtStack.top();
128 			fPtStack.pop();
129 		}
130 
131 		view->Window()->GetDrawingEngine()->DrawShape(frame, opCount, opList, ptCount, ptList,
132 				view->CurrentState(), filled);
133 	}
134 }
135 
136 static void
137 get_polygon_frame(const BPoint *points, int32 numPoints, BRect *_frame)
138 {
139 	float l, t, r, b;
140 
141 	ASSERT(numPoints > 0);
142 
143 	l = r = points->x;
144 	t = b = points->y;
145 
146 	points++;
147 	numPoints--;
148 
149 	while (numPoints--) {
150 		if (points->x < l)
151 			l = points->x;
152 		if (points->x > r)
153 			r = points->x;
154 		if (points->y < t)
155 			t = points->y;
156 		if (points->y > b)
157 			b = points->y;
158 		points++;
159 	}
160 
161 	_frame->Set(l, t, r, b);
162 }
163 
164 
165 static void
166 nop()
167 {
168 }
169 
170 
171 static void
172 move_pen_by(ViewLayer *view, BPoint delta)
173 {
174 	view->CurrentState()->SetPenLocation(delta - view->CurrentState()->PenLocation());
175 }
176 
177 
178 static void
179 stroke_line(ViewLayer *view, BPoint start, BPoint end)
180 {
181 	view->ConvertToScreenForDrawing(&start);
182 	view->ConvertToScreenForDrawing(&end);
183 	view->Window()->GetDrawingEngine()->StrokeLine(start, end, view->CurrentState());
184 }
185 
186 
187 static void
188 stroke_rect(ViewLayer *view, BRect rect)
189 {
190 	view->ConvertToScreenForDrawing(&rect);
191 	view->Window()->GetDrawingEngine()->StrokeRect(rect, view->CurrentState());
192 }
193 
194 
195 static void
196 fill_rect(ViewLayer *view, BRect rect)
197 {
198 	view->ConvertToScreenForDrawing(&rect);
199 	view->Window()->GetDrawingEngine()->FillRect(rect, view->CurrentState());
200 }
201 
202 
203 static void
204 stroke_round_rect(ViewLayer *view, BRect rect, BPoint radii)
205 {
206 	view->ConvertToScreenForDrawing(&rect);
207 	view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), false);
208 }
209 
210 
211 static void
212 fill_round_rect(ViewLayer *view, BRect rect, BPoint radii)
213 {
214 	view->ConvertToScreenForDrawing(&rect);
215 	view->Window()->GetDrawingEngine()->DrawRoundRect(rect, radii.x, radii.y, view->CurrentState(), true);
216 }
217 
218 
219 static void
220 stroke_bezier(ViewLayer *view, const BPoint *viewPoints)
221 {
222 	BPoint points[4];
223 	view->ConvertToScreenForDrawing(points, viewPoints, 4);
224 
225 	view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), false);
226 }
227 
228 
229 static void
230 fill_bezier(ViewLayer *view, const BPoint *viewPoints)
231 {
232 	BPoint points[4];
233 	view->ConvertToScreenForDrawing(points, viewPoints, 4);
234 
235 	view->Window()->GetDrawingEngine()->DrawBezier(points, view->CurrentState(), true);
236 }
237 
238 
239 static void
240 stroke_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta,
241 			   float arcTheta)
242 {
243 	BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
244 			center.y + radii.y);
245 	view->ConvertToScreenForDrawing(&rect);
246 	view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), false);
247 }
248 
249 
250 static void
251 fill_arc(ViewLayer *view, BPoint center, BPoint radii, float startTheta,
252 			 float arcTheta)
253 {
254 	BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
255 			center.y + radii.y);
256 	view->ConvertToScreenForDrawing(&rect);
257 	view->Window()->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, view->CurrentState(), true);
258 }
259 
260 
261 static void
262 stroke_ellipse(ViewLayer *view, BPoint center, BPoint radii)
263 {
264 	BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
265 			center.y + radii.y);
266 	view->ConvertToScreenForDrawing(&rect);
267 	view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), false);
268 }
269 
270 
271 static void
272 fill_ellipse(ViewLayer *view, BPoint center, BPoint radii)
273 {
274 	BRect rect(center.x - radii.x, center.y - radii.y, center.x + radii.x,
275 			center.y + radii.y);
276 	view->ConvertToScreenForDrawing(&rect);
277 	view->Window()->GetDrawingEngine()->DrawEllipse(rect, view->CurrentState(), true);
278 }
279 
280 
281 static void
282 stroke_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints, bool isClosed)
283 {
284 	if (numPoints <= 0) {
285 		return;
286 	} else if (numPoints <= 200) {
287 		// fast path: no malloc/free, also avoid constructor/destructor calls
288 		char data[200 * sizeof(BPoint)];
289 		BPoint *points = (BPoint *)data;
290 
291 		view->ConvertToScreenForDrawing(points, viewPoints, numPoints);
292 
293 		BRect polyFrame;
294 		get_polygon_frame(points, numPoints, &polyFrame);
295 
296 		view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
297 														view->CurrentState(), false,
298 														isClosed && numPoints > 2);
299 	} else {
300 		 // avoid constructor/destructor calls by using malloc instead of new []
301 		BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint));
302 		if (!points)
303 			return;
304 
305 		view->ConvertToScreenForDrawing(points, viewPoints, numPoints);
306 
307 		BRect polyFrame;
308 		get_polygon_frame(points, numPoints, &polyFrame);
309 
310 		view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
311 														view->CurrentState(), false,
312 														isClosed && numPoints > 2);
313 		free(points);
314 	}
315 }
316 
317 
318 static void
319 fill_polygon(ViewLayer *view, int32 numPoints, const BPoint *viewPoints)
320 {
321 	if (numPoints <= 0) {
322 		return;
323 	} else if (numPoints <= 200) {
324 		// fast path: no malloc/free, also avoid constructor/destructor calls
325 		char data[200 * sizeof(BPoint)];
326 		BPoint *points = (BPoint *)data;
327 
328 		view->ConvertToScreenForDrawing(points, viewPoints, numPoints);
329 
330 		BRect polyFrame;
331 		get_polygon_frame(points, numPoints, &polyFrame);
332 
333 		view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
334 														view->CurrentState(), true, true);
335 	} else {
336 		 // avoid constructor/destructor calls by using malloc instead of new []
337 		BPoint *points = (BPoint *)malloc(numPoints * sizeof(BPoint));
338 		if (!points)
339 			return;
340 
341 		view->ConvertToScreenForDrawing(points, viewPoints, numPoints);
342 
343 		BRect polyFrame;
344 		get_polygon_frame(points, numPoints, &polyFrame);
345 
346 		view->Window()->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
347 														view->CurrentState(), true, true);
348 		free(points);
349 	}
350 }
351 
352 
353 static void
354 stroke_shape(ViewLayer *view, const BShape *shape)
355 {
356 	ShapePainter drawShape;
357 
358 	drawShape.Iterate(shape);
359 	drawShape.Draw(view, shape->Bounds(), false);
360 }
361 
362 
363 static void
364 fill_shape(ViewLayer *view, const BShape *shape)
365 {
366 	ShapePainter drawShape;
367 
368 	drawShape.Iterate(shape);
369 	drawShape.Draw(view, shape->Bounds(), true);
370 }
371 
372 
373 static void
374 draw_string(ViewLayer *view, const char *string, float deltaSpace, float deltaNonSpace)
375 {
376 	BPoint location = view->CurrentState()->PenLocation();
377 	escapement_delta delta = {deltaSpace, deltaNonSpace };
378 	view->ConvertToScreenForDrawing(&location);
379 	view->Window()->GetDrawingEngine()->DrawString(string, strlen(string), location,
380 		view->CurrentState(), &delta);
381 	// TODO: Update pen location ?
382 
383 }
384 
385 
386 static void
387 draw_pixels(ViewLayer *view, BRect src, BRect dest, int32 width, int32 height,
388 				 int32 bytesPerRow, int32 pixelFormat, int32 flags, const void *data)
389 {
390 	// TODO: Review this
391 	UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1), (color_space)pixelFormat, flags, bytesPerRow);
392 
393 	if (!bitmap.IsValid())
394 		return;
395 
396 	memcpy(bitmap.Bits(), data, height * bytesPerRow);
397 
398 	view->ConvertToScreenForDrawing(&dest);
399 
400 	view->Window()->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, view->CurrentState());
401 }
402 
403 
404 static void
405 set_clipping_rects(ViewLayer *view, const BRect *rects, uint32 numRects)
406 {
407 	// TODO: This is too slow, we should copy the rects directly to BRegion's internal data
408 	BRegion region;
409 	for (uint32 c = 0; c < numRects; c++)
410 		region.Include(rects[c]);
411 	view->SetUserClipping(&region);
412 }
413 
414 
415 static void
416 clip_to_picture(ViewLayer *view, BPicture *picture, BPoint pt,
417 				   bool clip_to_inverse_picture)
418 {
419 	printf("ClipToPicture(picture, BPoint(%.2f, %.2f), %s)\n", pt.x, pt.y,
420 		clip_to_inverse_picture ? "inverse" : "");
421 }
422 
423 
424 static void
425 push_state(ViewLayer *view)
426 {
427 	view->PushState();
428 }
429 
430 
431 static void
432 pop_state(ViewLayer *view)
433 {
434 	view->PopState();
435 }
436 
437 
438 static void
439 enter_state_change(ViewLayer *view)
440 {
441 	printf("EnterStateChange\n");
442 }
443 
444 
445 static void
446 exit_state_change(ViewLayer *view)
447 {
448 	printf("ExitStateChange\n");
449 }
450 
451 
452 static void
453 enter_font_state(ViewLayer *view)
454 {
455 	printf("EnterFontState\n");
456 }
457 
458 
459 static void
460 exit_font_state(ViewLayer *view)
461 {
462 	printf("ExitFontState\n");
463 }
464 
465 
466 static void
467 set_origin(ViewLayer *view, BPoint pt)
468 {
469 	view->CurrentState()->SetOrigin(pt);
470 }
471 
472 
473 static void
474 set_pen_location(ViewLayer *view, BPoint pt)
475 {
476 	view->CurrentState()->SetPenLocation(pt);
477 }
478 
479 
480 static void
481 set_drawing_mode(ViewLayer *view, drawing_mode mode)
482 {
483 	view->CurrentState()->SetDrawingMode(mode);
484 }
485 
486 
487 static void
488 set_line_mode(ViewLayer *view, cap_mode capMode, join_mode joinMode, float miterLimit)
489 {
490 	DrawState *state = view->CurrentState();
491 	state->SetLineCapMode(capMode);
492 	state->SetLineJoinMode(joinMode);
493 	state->SetMiterLimit(miterLimit);
494 }
495 
496 
497 static void
498 set_pen_size(ViewLayer *view, float size)
499 {
500 	view->CurrentState()->SetPenSize(size);
501 }
502 
503 
504 static void
505 set_fore_color(ViewLayer *view, rgb_color color)
506 {
507 	view->CurrentState()->SetHighColor(RGBColor(color));
508 }
509 
510 
511 static void
512 set_back_color(ViewLayer *view, rgb_color color)
513 {
514 	view->CurrentState()->SetLowColor(RGBColor(color));
515 }
516 
517 
518 static void
519 set_stipple_pattern(ViewLayer *view, pattern p)
520 {
521 	printf("SetStipplePattern\n");
522 }
523 
524 
525 static void
526 set_scale(ViewLayer *view, float scale)
527 {
528 	view->CurrentState()->SetScale(scale);
529 }
530 
531 
532 static void
533 set_font_family(ViewLayer *view, const char *family)
534 {
535 	printf("SetFontFamily(%s)\n", family);
536 }
537 
538 
539 static void
540 set_font_style(ViewLayer *view, const char *style)
541 {
542 	printf("SetFontStyle(%s)\n", style);
543 }
544 
545 
546 static void
547 set_font_spacing(ViewLayer *view, int32 spacing)
548 {
549 	printf("SetFontSpacing(%ld)\n", spacing);
550 }
551 
552 
553 static void
554 set_font_size(ViewLayer *view, float size)
555 {
556 	ServerFont font;
557 	font.SetSize(size);
558 	view->CurrentState()->SetFont(font, B_FONT_SIZE);
559 }
560 
561 
562 static void
563 set_font_rotate(ViewLayer *view, float rotation)
564 {
565 	printf("SetFontRotate(%.2f)\n", rotation);
566 }
567 
568 
569 static void
570 set_font_encoding(ViewLayer *view, int32 encoding)
571 {
572 	printf("SetFontEncoding(%ld)\n", encoding);
573 }
574 
575 
576 static void
577 set_font_flags(ViewLayer *view, int32 flags)
578 {
579 	printf("SetFontFlags(%ld)\n", flags);
580 }
581 
582 
583 static void
584 set_font_shear(ViewLayer *view, float shear)
585 {
586 	printf("SetFontShear(%.2f)\n", shear);
587 }
588 
589 
590 static void
591 set_font_face(ViewLayer *view, int32 flags)
592 {
593 	printf("SetFontFace(%ld)\n", flags);
594 }
595 
596 
597 static void
598 set_blending_mode(ViewLayer *view, int16 alphaSrcMode, int16 alphaFncMode)
599 {
600 	view->CurrentState()->SetBlendingMode((source_alpha)alphaSrcMode, (alpha_function)alphaFncMode);
601 }
602 
603 
604 static void
605 reserved()
606 {
607 }
608 
609 
610 const void *tableEntries[] = {
611 	(const void *)nop,
612 	(const void *)move_pen_by,
613 	(const void *)stroke_line,
614 	(const void *)stroke_rect,
615 	(const void *)fill_rect,
616 	(const void *)stroke_round_rect,
617 	(const void *)fill_round_rect,
618 	(const void *)stroke_bezier,
619 	(const void *)fill_bezier,
620 	(const void *)stroke_arc,
621 	(const void *)fill_arc,
622 	(const void *)stroke_ellipse,
623 	(const void *)fill_ellipse,
624 	(const void *)stroke_polygon,
625 	(const void *)fill_polygon,
626 	(const void *)stroke_shape,
627 	(const void *)fill_shape,
628 	(const void *)draw_string,
629 	(const void *)draw_pixels,
630 	(const void *)reserved,	// TODO: This is probably "draw_picture". Investigate
631 	(const void *)set_clipping_rects,
632 	(const void *)clip_to_picture,
633 	(const void *)push_state,
634 	(const void *)pop_state,
635 	(const void *)enter_state_change,
636 	(const void *)exit_state_change,
637 	(const void *)enter_font_state,
638 	(const void *)exit_font_state,
639 	(const void *)set_origin,
640 	(const void *)set_pen_location,
641 	(const void *)set_drawing_mode,
642 	(const void *)set_line_mode,
643 	(const void *)set_pen_size,
644 	(const void *)set_fore_color,
645 	(const void *)set_back_color,
646 	(const void *)set_stipple_pattern,
647 	(const void *)set_scale,
648 	(const void *)set_font_family,
649 	(const void *)set_font_style,
650 	(const void *)set_font_spacing,
651 	(const void *)set_font_size,
652 	(const void *)set_font_rotate,
653 	(const void *)set_font_encoding,
654 	(const void *)set_font_flags,
655 	(const void *)set_font_shear,
656 	(const void *)reserved,		// TODO: Marc Flerackers calls this "set_font_bpp". Investigate
657 	(const void *)set_font_face, // TODO: R5 function table ends here... how is set blending mode implemented there ?
658 	(const void *)set_blending_mode
659 };
660 
661 
662 // ServerPicture
663 ServerPicture::ServerPicture()
664 	:PictureDataWriter(&fData)
665 {
666 	fToken = gTokenSpace.NewToken(kPictureToken, this);
667 }
668 
669 
670 ServerPicture::ServerPicture(const ServerPicture &picture)
671 	:PictureDataWriter(&fData)
672 {
673 	fToken = gTokenSpace.NewToken(kPictureToken, this);
674 
675 	fData.Write(picture.Data(), picture.DataLength());
676 }
677 
678 
679 ServerPicture::~ServerPicture()
680 {
681 }
682 
683 
684 void
685 ServerPicture::SyncState(ViewLayer *view)
686 {
687 	// TODO: Finish this
688 	BeginOp(B_PIC_ENTER_STATE_CHANGE);
689 
690 //	WriteSetPenLocation(view->CurrentState()->PenLocation());
691 	WriteSetPenSize(view->CurrentState()->PenSize());
692 	WriteSetScale(view->CurrentState()->Scale());
693 	WriteSetLineMode(view->CurrentState()->LineCapMode(), view->CurrentState()->LineJoinMode(),
694 			view->CurrentState()->MiterLimit());
695 
696 /*
697 	BeginOp(B_PIC_SET_STIPLE_PATTERN);
698 	AddData(view->CurrentState()->GetPattern().GetInt8(), sizeof(pattern));
699 	EndOp();
700 */
701 	WriteSetDrawingMode(view->CurrentState()->GetDrawingMode());
702 
703 	/*BeginOp(B_PIC_SET_BLENDING_MODE);
704 	AddInt16((int16)view->CurrentState()->AlphaSrcMode());
705 	AddInt16((int16)view->CurrentState()->AlphaFncMode());
706 	EndOp();
707 */
708 	WriteSetHighColor(view->CurrentState()->HighColor().GetColor32());
709 	WriteSetLowColor(view->CurrentState()->LowColor().GetColor32());
710 
711 	EndOp();
712 
713 }
714 
715 
716 void
717 ServerPicture::Play(ViewLayer *view)
718 {
719 	PicturePlayer player(fData.Buffer(), fData.BufferLength(), NULL);
720 	player.Play(const_cast<void **>(tableEntries), sizeof(tableEntries) / sizeof(void *), view);
721 }
722 
723 
724 status_t
725 ServerPicture::ImportData(BPrivate::LinkReceiver &link)
726 {
727 	int32 subPicturesCount = 0;
728 	link.Read<int32>(&subPicturesCount);
729 	for (int32 c = 0; c < subPicturesCount; c++) {
730 		// TODO: Support nested pictures
731 	}
732 
733 	int32 size = 0;
734 	link.Read<int32>(&size);
735 	if (fData.SetSize(size) != B_OK)
736 		return B_ERROR;
737 
738 	// TODO: The best way to do this would be to read the data into
739 	// a temporary buffer, and then use the BMallocIO::Write() method,
740 	// but this way we avoid an extra copy. Unfortunately BMallocIO::Write()
741 	// only accepts a pointer to raw data...
742 	link.Read(const_cast<void *>(fData.Buffer()), size);
743 
744 	return B_OK;
745 }
746