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