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