usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / servers / app / ServerPicture.cpp
blob01808141a0e5af3f20370b9f6964666ae7e13070
1 /*
2 * Copyright 2001-2015, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stefano Ceccherini (stefano.ceccherini@gmail.com)
8 * Marcus Overhagen <marcus@overhagen.de>
9 * Julian Harnath <julian.harnath@rwth-aachen.de>
12 #include "ServerPicture.h"
14 #include <new>
15 #include <stdio.h>
16 #include <stack>
18 #include "AlphaMask.h"
19 #include "DrawingEngine.h"
20 #include "DrawState.h"
21 #include "FontManager.h"
22 #include "Layer.h"
23 #include "ServerApp.h"
24 #include "ServerBitmap.h"
25 #include "ServerFont.h"
26 #include "ServerTokenSpace.h"
27 #include "View.h"
28 #include "Window.h"
30 #include <LinkReceiver.h>
31 #include <OffsetFile.h>
32 #include <ObjectListPrivate.h>
33 #include <PicturePlayer.h>
34 #include <PictureProtocol.h>
35 #include <PortLink.h>
36 #include <ServerProtocol.h>
37 #include <ShapePrivate.h>
39 #include <Bitmap.h>
40 #include <Debug.h>
41 #include <List.h>
42 #include <Shape.h>
45 using std::stack;
48 class ShapePainter : public BShapeIterator {
49 public:
50 ShapePainter(Canvas* canvas);
51 virtual ~ShapePainter();
53 status_t Iterate(const BShape* shape);
55 virtual status_t IterateMoveTo(BPoint* point);
56 virtual status_t IterateLineTo(int32 lineCount, BPoint* linePts);
57 virtual status_t IterateBezierTo(int32 bezierCount, BPoint* bezierPts);
58 virtual status_t IterateClose();
59 virtual status_t IterateArcTo(float& rx, float& ry,
60 float& angle, bool largeArc, bool counterClockWise, BPoint& point);
62 void Draw(BRect frame, bool filled);
64 private:
65 Canvas* fCanvas;
66 stack<uint32> fOpStack;
67 stack<BPoint> fPtStack;
71 ShapePainter::ShapePainter(Canvas* canvas)
73 fCanvas(canvas)
78 ShapePainter::~ShapePainter()
83 status_t
84 ShapePainter::Iterate(const BShape* shape)
86 // this class doesn't modify the shape data
87 return BShapeIterator::Iterate(const_cast<BShape*>(shape));
91 status_t
92 ShapePainter::IterateMoveTo(BPoint* point)
94 try {
95 fOpStack.push(OP_MOVETO);
96 fPtStack.push(*point);
97 } catch (std::bad_alloc) {
98 return B_NO_MEMORY;
101 return B_OK;
105 status_t
106 ShapePainter::IterateLineTo(int32 lineCount, BPoint* linePts)
108 try {
109 fOpStack.push(OP_LINETO | lineCount);
110 for (int32 i = 0; i < lineCount; i++)
111 fPtStack.push(linePts[i]);
112 } catch (std::bad_alloc) {
113 return B_NO_MEMORY;
116 return B_OK;
120 status_t
121 ShapePainter::IterateBezierTo(int32 bezierCount, BPoint* bezierPts)
123 bezierCount *= 3;
124 try {
125 fOpStack.push(OP_BEZIERTO | bezierCount);
126 for (int32 i = 0; i < bezierCount; i++)
127 fPtStack.push(bezierPts[i]);
128 } catch (std::bad_alloc) {
129 return B_NO_MEMORY;
132 return B_OK;
136 status_t
137 ShapePainter::IterateArcTo(float& rx, float& ry,
138 float& angle, bool largeArc, bool counterClockWise, BPoint& point)
140 uint32 op;
141 if (largeArc) {
142 if (counterClockWise)
143 op = OP_LARGE_ARC_TO_CCW;
144 else
145 op = OP_LARGE_ARC_TO_CW;
146 } else {
147 if (counterClockWise)
148 op = OP_SMALL_ARC_TO_CCW;
149 else
150 op = OP_SMALL_ARC_TO_CW;
153 try {
154 fOpStack.push(op | 3);
155 fPtStack.push(BPoint(rx, ry));
156 fPtStack.push(BPoint(angle, 0));
157 fPtStack.push(point);
158 } catch (std::bad_alloc) {
159 return B_NO_MEMORY;
162 return B_OK;
166 status_t
167 ShapePainter::IterateClose()
169 try {
170 fOpStack.push(OP_CLOSE);
171 } catch (std::bad_alloc) {
172 return B_NO_MEMORY;
175 return B_OK;
179 void
180 ShapePainter::Draw(BRect frame, bool filled)
182 // We're going to draw the currently iterated shape.
183 // TODO: This can be more efficient by skipping the conversion.
184 int32 opCount = fOpStack.size();
185 int32 ptCount = fPtStack.size();
187 if (opCount > 0 && ptCount > 0) {
188 int32 i;
189 uint32* opList = new(std::nothrow) uint32[opCount];
190 if (opList == NULL)
191 return;
193 BPoint* ptList = new(std::nothrow) BPoint[ptCount];
194 if (ptList == NULL) {
195 delete[] opList;
196 return;
199 for (i = opCount - 1; i >= 0; i--) {
200 opList[i] = fOpStack.top();
201 fOpStack.pop();
204 for (i = ptCount - 1; i >= 0; i--) {
205 ptList[i] = fPtStack.top();
206 fPtStack.pop();
209 BPoint offset(fCanvas->CurrentState()->PenLocation());
210 fCanvas->PenToScreenTransform().Apply(&offset);
211 fCanvas->GetDrawingEngine()->DrawShape(frame, opCount, opList,
212 ptCount, ptList, filled, offset, fCanvas->Scale());
214 delete[] opList;
215 delete[] ptList;
220 // #pragma mark - drawing functions
223 static void
224 get_polygon_frame(const BPoint* points, uint32 numPoints, BRect* _frame)
226 ASSERT(numPoints > 0);
228 float left = points->x;
229 float top = points->y;
230 float right = left;
231 float bottom = top;
233 points++;
234 numPoints--;
236 while (numPoints--) {
237 if (points->x < left)
238 left = points->x;
239 if (points->x > right)
240 right = points->x;
241 if (points->y < top)
242 top = points->y;
243 if (points->y > bottom)
244 bottom = points->y;
245 points++;
248 _frame->Set(left, top, right, bottom);
252 static void
253 move_pen_by(void* _canvas, const BPoint& delta)
255 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
256 canvas->CurrentState()->SetPenLocation(
257 canvas->CurrentState()->PenLocation() + delta);
261 static void
262 stroke_line(void* _canvas, const BPoint& _start, const BPoint& _end)
264 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
265 BPoint start = _start;
266 BPoint end = _end;
268 const SimpleTransform transform = canvas->PenToScreenTransform();
269 transform.Apply(&start);
270 transform.Apply(&end);
271 canvas->GetDrawingEngine()->StrokeLine(start, end);
273 canvas->CurrentState()->SetPenLocation(_end);
274 // the DrawingEngine/Painter does not need to be updated, since this
275 // effects only the view->screen coord conversion, which is handled
276 // by the view only
280 static void
281 draw_rect(void* _canvas, const BRect& _rect, bool fill)
283 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
284 BRect rect = _rect;
286 canvas->PenToScreenTransform().Apply(&rect);
287 if (fill)
288 canvas->GetDrawingEngine()->FillRect(rect);
289 else
290 canvas->GetDrawingEngine()->StrokeRect(rect);
294 static void
295 draw_round_rect(void* _canvas, const BRect& _rect, const BPoint& radii,
296 bool fill)
298 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
299 BRect rect = _rect;
301 canvas->PenToScreenTransform().Apply(&rect);
302 float scale = canvas->CurrentState()->CombinedScale();
303 canvas->GetDrawingEngine()->DrawRoundRect(rect, radii.x * scale,
304 radii.y * scale, fill);
308 static void
309 draw_bezier(void* _canvas, size_t numPoints, const BPoint viewPoints[],
310 bool fill)
312 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
314 const size_t kSupportedPoints = 4;
315 if (numPoints != kSupportedPoints)
316 return;
318 BPoint points[kSupportedPoints];
319 canvas->PenToScreenTransform().Apply(points, viewPoints, kSupportedPoints);
320 canvas->GetDrawingEngine()->DrawBezier(points, fill);
324 static void
325 draw_arc(void* _canvas, const BPoint& center, const BPoint& radii,
326 float startTheta, float arcTheta, bool fill)
328 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
330 BRect rect(center.x - radii.x, center.y - radii.y,
331 center.x + radii.x - 1, center.y + radii.y - 1);
332 canvas->PenToScreenTransform().Apply(&rect);
333 canvas->GetDrawingEngine()->DrawArc(rect, startTheta, arcTheta, fill);
337 static void
338 draw_ellipse(void* _canvas, const BRect& _rect, bool fill)
340 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
342 BRect rect = _rect;
343 canvas->PenToScreenTransform().Apply(&rect);
344 canvas->GetDrawingEngine()->DrawEllipse(rect, fill);
348 static void
349 draw_polygon(void* _canvas, size_t numPoints, const BPoint viewPoints[],
350 bool isClosed, bool fill)
352 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
354 if (numPoints == 0)
355 return;
357 const size_t kMaxStackCount = 200;
358 char stackData[kMaxStackCount * sizeof(BPoint)];
359 BPoint* points = (BPoint*)stackData;
360 if (numPoints > kMaxStackCount) {
361 points = (BPoint*)malloc(numPoints * sizeof(BPoint));
362 if (points == NULL)
363 return;
366 canvas->PenToScreenTransform().Apply(points, viewPoints, numPoints);
368 BRect polyFrame;
369 get_polygon_frame(points, numPoints, &polyFrame);
371 canvas->GetDrawingEngine()->DrawPolygon(points, numPoints, polyFrame,
372 fill, isClosed && numPoints > 2);
374 if (numPoints > kMaxStackCount)
375 free(points);
379 static void
380 draw_shape(void* _canvas, const BShape& shape, bool fill)
382 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
383 ShapePainter drawShape(canvas);
385 drawShape.Iterate(&shape);
386 drawShape.Draw(shape.Bounds(), fill);
390 static void
391 draw_string(void* _canvas, const char* string, size_t length, float deltaSpace,
392 float deltaNonSpace)
394 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
396 // NOTE: the picture data was recorded with a "set pen location"
397 // command inserted before the "draw string" command, so we can
398 // use PenLocation()
399 BPoint location = canvas->CurrentState()->PenLocation();
401 escapement_delta delta = { deltaSpace, deltaNonSpace };
402 canvas->PenToScreenTransform().Apply(&location);
403 location = canvas->GetDrawingEngine()->DrawString(string, length,
404 location, &delta);
406 canvas->PenToScreenTransform().Apply(&location);
407 canvas->CurrentState()->SetPenLocation(location);
408 // the DrawingEngine/Painter does not need to be updated, since this
409 // effects only the view->screen coord conversion, which is handled
410 // by the view only
414 static void
415 draw_pixels(void* _canvas, const BRect& src, const BRect& _dest, uint32 width,
416 uint32 height, size_t bytesPerRow, color_space pixelFormat, uint32 options,
417 const void* data, size_t length)
419 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
421 UtilityBitmap bitmap(BRect(0, 0, width - 1, height - 1),
422 (color_space)pixelFormat, 0, bytesPerRow);
424 if (!bitmap.IsValid())
425 return;
427 memcpy(bitmap.Bits(), data, std::min(height * bytesPerRow, length));
429 BRect dest = _dest;
430 canvas->PenToScreenTransform().Apply(&dest);
431 canvas->GetDrawingEngine()->DrawBitmap(&bitmap, src, dest, options);
435 static void
436 draw_picture(void* _canvas, const BPoint& where, int32 token)
438 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
440 ServerPicture* picture = canvas->GetPicture(token);
441 if (picture != NULL) {
442 canvas->PushState();
443 canvas->SetDrawingOrigin(where);
445 canvas->PushState();
446 picture->Play(canvas);
447 canvas->PopState();
449 canvas->PopState();
450 picture->ReleaseReference();
455 static void
456 set_clipping_rects(void* _canvas, size_t numRects, const BRect rects[])
458 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
460 if (numRects == 0)
461 canvas->SetUserClipping(NULL);
462 else {
463 // TODO: This might be too slow, we should copy the rects
464 // directly to BRegion's internal data
465 BRegion region;
466 for (uint32 c = 0; c < numRects; c++)
467 region.Include(rects[c]);
468 canvas->SetUserClipping(&region);
470 canvas->UpdateCurrentDrawingRegion();
474 static void
475 clip_to_picture(void* _canvas, int32 pictureToken, const BPoint& where,
476 bool clipToInverse)
478 /* TODO
479 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
481 ServerPicture* picture = canvas->GetPicture(pictureToken);
482 if (picture == NULL)
483 return;
485 AlphaMask* mask = new(std::nothrow) AlphaMask(
486 picture, clipToInverse, where, *canvas->CurrentState());
487 canvas->SetAlphaMask(mask);
488 canvas->UpdateCurrentDrawingRegion();
489 if (mask != NULL)
490 mask->ReleaseReference();
492 picture->ReleaseReference();
497 static void
498 push_state(void* _canvas)
500 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
501 canvas->PushState();
505 static void
506 pop_state(void* _canvas)
508 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
509 canvas->PopState();
511 BPoint p(0, 0);
512 canvas->PenToScreenTransform().Apply(&p);
513 canvas->GetDrawingEngine()->SetDrawState(canvas->CurrentState(),
514 (int32)p.x, (int32)p.y);
518 // TODO: Be smart and actually take advantage of these methods:
519 // only apply state changes when they are called
520 static void
521 enter_state_change(void* _canvas)
526 static void
527 exit_state_change(void* _canvas)
529 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
530 canvas->ResyncDrawState();
534 static void
535 enter_font_state(void* _canvas)
540 static void
541 exit_font_state(void* _canvas)
543 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
544 canvas->GetDrawingEngine()->SetFont(canvas->CurrentState()->Font());
548 static void
549 set_origin(void* _canvas, const BPoint& pt)
551 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
552 canvas->CurrentState()->SetOrigin(pt);
556 static void
557 set_pen_location(void* _canvas, const BPoint& pt)
559 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
560 canvas->CurrentState()->SetPenLocation(pt);
561 // the DrawingEngine/Painter does not need to be updated, since this
562 // effects only the view->screen coord conversion, which is handled
563 // by the view only
567 static void
568 set_drawing_mode(void* _canvas, drawing_mode mode)
570 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
571 if (canvas->CurrentState()->SetDrawingMode(mode))
572 canvas->GetDrawingEngine()->SetDrawingMode(mode);
576 static void
577 set_line_mode(void* _canvas, cap_mode capMode, join_mode joinMode,
578 float miterLimit)
580 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
581 DrawState* state = canvas->CurrentState();
582 state->SetLineCapMode(capMode);
583 state->SetLineJoinMode(joinMode);
584 state->SetMiterLimit(miterLimit);
585 canvas->GetDrawingEngine()->SetStrokeMode(capMode, joinMode, miterLimit);
589 static void
590 set_pen_size(void* _canvas, float size)
592 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
593 canvas->CurrentState()->SetPenSize(size);
594 canvas->GetDrawingEngine()->SetPenSize(
595 canvas->CurrentState()->PenSize());
596 // DrawState::PenSize() returns the scaled pen size, so we
597 // need to use that value to set the drawing engine pen size.
601 static void
602 set_fore_color(void* _canvas, const rgb_color& color)
604 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
605 canvas->CurrentState()->SetHighColor(color);
606 canvas->GetDrawingEngine()->SetHighColor(color);
610 static void
611 set_back_color(void* _canvas, const rgb_color& color)
613 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
614 canvas->CurrentState()->SetLowColor(color);
615 canvas->GetDrawingEngine()->SetLowColor(color);
619 static void
620 set_stipple_pattern(void* _canvas, const pattern& pattern)
622 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
623 canvas->CurrentState()->SetPattern(Pattern(pattern));
624 canvas->GetDrawingEngine()->SetPattern(pattern);
628 static void
629 set_scale(void* _canvas, float scale)
631 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
632 canvas->CurrentState()->SetScale(scale);
633 canvas->ResyncDrawState();
635 // Update the drawing engine draw state, since some stuff
636 // (for example the pen size) needs to be recalculated.
640 static void
641 set_font_family(void* _canvas, const char* _family, size_t length)
643 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
644 BString family(_family, length);
646 FontStyle* fontStyle = gFontManager->GetStyleByIndex(family, 0);
647 ServerFont font;
648 font.SetStyle(fontStyle);
649 canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
653 static void
654 set_font_style(void* _canvas, const char* _style, size_t length)
656 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
657 BString style(_style, length);
659 ServerFont font(canvas->CurrentState()->Font());
661 FontStyle* fontStyle = gFontManager->GetStyle(font.Family(), style);
663 font.SetStyle(fontStyle);
664 canvas->CurrentState()->SetFont(font, B_FONT_FAMILY_AND_STYLE);
668 static void
669 set_font_spacing(void* _canvas, uint8 spacing)
671 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
672 ServerFont font;
673 font.SetSpacing(spacing);
674 canvas->CurrentState()->SetFont(font, B_FONT_SPACING);
678 static void
679 set_font_size(void* _canvas, float size)
681 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
682 ServerFont font;
683 font.SetSize(size);
684 canvas->CurrentState()->SetFont(font, B_FONT_SIZE);
688 static void
689 set_font_rotation(void* _canvas, float rotation)
691 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
692 ServerFont font;
693 font.SetRotation(rotation);
694 canvas->CurrentState()->SetFont(font, B_FONT_ROTATION);
698 static void
699 set_font_encoding(void* _canvas, uint8 encoding)
701 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
702 ServerFont font;
703 font.SetEncoding(encoding);
704 canvas->CurrentState()->SetFont(font, B_FONT_ENCODING);
708 static void
709 set_font_flags(void* _canvas, uint32 flags)
711 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
712 ServerFont font;
713 font.SetFlags(flags);
714 canvas->CurrentState()->SetFont(font, B_FONT_FLAGS);
718 static void
719 set_font_shear(void* _canvas, float shear)
721 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
722 ServerFont font;
723 font.SetShear(shear);
724 canvas->CurrentState()->SetFont(font, B_FONT_SHEAR);
728 static void
729 set_font_face(void* _canvas, uint16 face)
731 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
732 ServerFont font;
733 font.SetFace(face);
734 canvas->CurrentState()->SetFont(font, B_FONT_FACE);
738 static void
739 set_blending_mode(void* _canvas, source_alpha alphaSrcMode,
740 alpha_function alphaFncMode)
742 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
743 canvas->CurrentState()->SetBlendingMode(alphaSrcMode, alphaFncMode);
747 static void
748 set_transform(void* _canvas, const BAffineTransform& transform)
750 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
751 canvas->CurrentState()->SetTransform(transform);
752 canvas->GetDrawingEngine()->SetTransform(transform);
756 static void
757 translate_by(void* _canvas, double x, double y)
759 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
760 BAffineTransform transform = canvas->CurrentState()->Transform();
761 transform.PreTranslateBy(x, y);
762 canvas->CurrentState()->SetTransform(transform);
763 canvas->GetDrawingEngine()->SetTransform(transform);
767 static void
768 scale_by(void* _canvas, double x, double y)
770 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
771 BAffineTransform transform = canvas->CurrentState()->Transform();
772 transform.PreScaleBy(x, y);
773 canvas->CurrentState()->SetTransform(transform);
774 canvas->GetDrawingEngine()->SetTransform(transform);
778 static void
779 rotate_by(void* _canvas, double angleRadians)
781 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
782 BAffineTransform transform = canvas->CurrentState()->Transform();
783 transform.PreRotateBy(angleRadians);
784 canvas->CurrentState()->SetTransform(transform);
785 canvas->GetDrawingEngine()->SetTransform(transform);
789 static void
790 blend_layer(void* _canvas, Layer* layer)
792 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
793 canvas->BlendLayer(layer);
797 static void
798 clip_to_rect(void* _canvas, const BRect& rect, bool inverse)
800 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
801 bool needDrawStateUpdate = canvas->ClipToRect(rect, inverse);
802 if (needDrawStateUpdate) {
803 canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
804 canvas->Bounds());
805 canvas->ResyncDrawState();
807 canvas->UpdateCurrentDrawingRegion();
811 static void
812 clip_to_shape(void* _canvas, int32 opCount, const uint32 opList[],
813 int32 ptCount, const BPoint ptList[], bool inverse)
815 Canvas* const canvas = reinterpret_cast<Canvas*>(_canvas);
816 shape_data shapeData;
818 // TODO: avoid copies
819 shapeData.opList = (uint32*)malloc(opCount * sizeof(uint32));
820 memcpy(shapeData.opList, opList, opCount * sizeof(uint32));
821 shapeData.ptList = (BPoint*)malloc(ptCount * sizeof(BPoint));
822 memcpy(shapeData.ptList, ptList, ptCount * sizeof(BPoint));
824 shapeData.opCount = opCount;
825 shapeData.opSize = opCount * sizeof(uint32);
826 shapeData.ptCount = ptCount;
827 shapeData.ptSize = ptCount * sizeof(BPoint);
829 canvas->ClipToShape(&shapeData, inverse);
830 canvas->CurrentState()->GetAlphaMask()->SetCanvasGeometry(BPoint(0, 0),
831 canvas->Bounds());
832 canvas->ResyncDrawState();
834 free(shapeData.opList);
835 free(shapeData.ptList);
839 static const BPrivate::picture_player_callbacks kPicturePlayerCallbacks = {
840 move_pen_by,
841 stroke_line,
842 draw_rect,
843 draw_round_rect,
844 draw_bezier,
845 draw_arc,
846 draw_ellipse,
847 draw_polygon,
848 draw_shape,
849 draw_string,
850 draw_pixels,
851 draw_picture,
852 set_clipping_rects,
853 clip_to_picture,
854 push_state,
855 pop_state,
856 enter_state_change,
857 exit_state_change,
858 enter_font_state,
859 exit_font_state,
860 set_origin,
861 set_pen_location,
862 set_drawing_mode,
863 set_line_mode,
864 set_pen_size,
865 set_fore_color,
866 set_back_color,
867 set_stipple_pattern,
868 set_scale,
869 set_font_family,
870 set_font_style,
871 set_font_spacing,
872 set_font_size,
873 set_font_rotation,
874 set_font_encoding,
875 set_font_flags,
876 set_font_shear,
877 set_font_face,
878 set_blending_mode,
879 set_transform,
880 translate_by,
881 scale_by,
882 rotate_by,
883 blend_layer,
884 clip_to_rect,
885 clip_to_shape
889 // #pragma mark - ServerPicture
892 ServerPicture::ServerPicture()
894 fFile(NULL),
895 fPictures(NULL),
896 fPushed(NULL),
897 fOwner(NULL)
899 fToken = gTokenSpace.NewToken(kPictureToken, this);
900 fData = new(std::nothrow) BMallocIO();
902 PictureDataWriter::SetTo(fData);
906 ServerPicture::ServerPicture(const ServerPicture& picture)
908 fFile(NULL),
909 fData(NULL),
910 fPictures(NULL),
911 fPushed(NULL),
912 fOwner(NULL)
914 fToken = gTokenSpace.NewToken(kPictureToken, this);
916 BMallocIO* mallocIO = new(std::nothrow) BMallocIO();
917 if (mallocIO == NULL)
918 return;
920 fData = mallocIO;
922 const off_t size = picture.DataLength();
923 if (mallocIO->SetSize(size) < B_OK)
924 return;
926 picture.fData->ReadAt(0, const_cast<void*>(mallocIO->Buffer()),
927 size);
929 PictureDataWriter::SetTo(fData);
933 ServerPicture::ServerPicture(const char* fileName, int32 offset)
935 fFile(NULL),
936 fData(NULL),
937 fPictures(NULL),
938 fPushed(NULL),
939 fOwner(NULL)
941 fToken = gTokenSpace.NewToken(kPictureToken, this);
943 fFile = new(std::nothrow) BFile(fileName, B_READ_WRITE);
944 if (fFile == NULL)
945 return;
947 BPrivate::Storage::OffsetFile* offsetFile
948 = new(std::nothrow) BPrivate::Storage::OffsetFile(fFile, offset);
949 if (offsetFile == NULL || offsetFile->InitCheck() != B_OK) {
950 delete offsetFile;
951 return;
954 fData = offsetFile;
956 PictureDataWriter::SetTo(fData);
960 ServerPicture::~ServerPicture()
962 ASSERT(fOwner == NULL);
964 delete fData;
965 delete fFile;
966 gTokenSpace.RemoveToken(fToken);
968 if (fPictures != NULL) {
969 for (int32 i = fPictures->CountItems(); i-- > 0;) {
970 ServerPicture* picture = fPictures->ItemAt(i);
971 picture->SetOwner(NULL);
972 picture->ReleaseReference();
975 delete fPictures;
978 if (fPushed != NULL) {
979 fPushed->SetOwner(NULL);
980 fPushed->ReleaseReference();
985 bool
986 ServerPicture::SetOwner(ServerApp* owner)
988 if (owner == fOwner)
989 return true;
991 // Acquire an extra reference, since calling RemovePicture()
992 // May remove the last reference and then we will self-destruct right then.
993 // Setting fOwner to NULL would access free'd memory. If owner is another
994 // ServerApp, it's expected to already have a reference of course.
995 BReference<ServerPicture> _(this);
997 if (fOwner != NULL)
998 fOwner->RemovePicture(this);
1000 fOwner = NULL;
1001 if (owner == NULL)
1002 return true;
1004 if (!owner->AddPicture(this))
1005 return false;
1007 fOwner = owner;
1008 return true;
1012 void
1013 ServerPicture::EnterStateChange()
1015 BeginOp(B_PIC_ENTER_STATE_CHANGE);
1019 void
1020 ServerPicture::ExitStateChange()
1022 EndOp();
1026 void
1027 ServerPicture::SyncState(View* view)
1029 // TODO: Finish this
1030 EnterStateChange();
1032 WriteSetOrigin(view->CurrentState()->Origin());
1033 WriteSetPenLocation(view->CurrentState()->PenLocation());
1034 WriteSetPenSize(view->CurrentState()->UnscaledPenSize());
1035 WriteSetScale(view->CurrentState()->Scale());
1036 WriteSetLineMode(view->CurrentState()->LineCapMode(),
1037 view->CurrentState()->LineJoinMode(),
1038 view->CurrentState()->MiterLimit());
1039 //WriteSetPattern(*view->CurrentState()->GetPattern().GetInt8());
1040 WriteSetDrawingMode(view->CurrentState()->GetDrawingMode());
1042 WriteSetHighColor(view->CurrentState()->HighColor());
1043 WriteSetLowColor(view->CurrentState()->LowColor());
1045 ExitStateChange();
1049 void
1050 ServerPicture::SetFontFromLink(BPrivate::LinkReceiver& link)
1052 BeginOp(B_PIC_ENTER_FONT_STATE);
1054 uint16 mask;
1055 link.Read<uint16>(&mask);
1057 if (mask & B_FONT_FAMILY_AND_STYLE) {
1058 uint32 fontID;
1059 link.Read<uint32>(&fontID);
1060 ServerFont font;
1061 font.SetFamilyAndStyle(fontID);
1062 WriteSetFontFamily(font.Family());
1063 WriteSetFontStyle(font.Style());
1066 if (mask & B_FONT_SIZE) {
1067 float size;
1068 link.Read<float>(&size);
1069 WriteSetFontSize(size);
1072 if (mask & B_FONT_SHEAR) {
1073 float shear;
1074 link.Read<float>(&shear);
1075 WriteSetFontShear(shear);
1078 if (mask & B_FONT_ROTATION) {
1079 float rotation;
1080 link.Read<float>(&rotation);
1081 WriteSetFontRotation(rotation);
1084 if (mask & B_FONT_FALSE_BOLD_WIDTH) {
1085 float falseBoldWidth;
1086 link.Read<float>(&falseBoldWidth);
1087 //SetFalseBoldWidth(falseBoldWidth);
1090 if (mask & B_FONT_SPACING) {
1091 uint8 spacing;
1092 link.Read<uint8>(&spacing);
1093 WriteSetFontSpacing(spacing);
1096 if (mask & B_FONT_ENCODING) {
1097 uint8 encoding;
1098 link.Read<uint8>((uint8*)&encoding);
1099 WriteSetFontEncoding(encoding);
1102 if (mask & B_FONT_FACE) {
1103 uint16 face;
1104 link.Read<uint16>(&face);
1105 WriteSetFontFace(face);
1108 if (mask & B_FONT_FLAGS) {
1109 uint32 flags;
1110 link.Read<uint32>(&flags);
1111 WriteSetFontFlags(flags);
1114 EndOp();
1118 void
1119 ServerPicture::Play(Canvas* target)
1121 // TODO: for now: then change PicturePlayer
1122 // to accept a BPositionIO object
1123 BMallocIO* mallocIO = dynamic_cast<BMallocIO*>(fData);
1124 if (mallocIO == NULL)
1125 return;
1127 BPrivate::PicturePlayer player(mallocIO->Buffer(),
1128 mallocIO->BufferLength(), PictureList::Private(fPictures).AsBList());
1129 player.Play(kPicturePlayerCallbacks, sizeof(kPicturePlayerCallbacks),
1130 target);
1134 /*! Acquires a reference to the pushed picture.
1136 void
1137 ServerPicture::PushPicture(ServerPicture* picture)
1139 if (fPushed != NULL)
1140 debugger("already pushed a picture");
1142 fPushed = picture;
1143 fPushed->AcquireReference();
1147 /*! Returns a reference with the popped picture.
1149 ServerPicture*
1150 ServerPicture::PopPicture()
1152 ServerPicture* old = fPushed;
1153 fPushed = NULL;
1154 return old;
1158 void
1159 ServerPicture::AppendPicture(ServerPicture* picture)
1161 // A pushed picture is the same as an appended one
1162 PushPicture(picture);
1166 bool
1167 ServerPicture::NestPicture(ServerPicture* picture)
1169 if (fPictures == NULL)
1170 fPictures = new(std::nothrow) PictureList;
1172 if (fPictures == NULL || !fPictures->AddItem(picture))
1173 return false;
1175 picture->AcquireReference();
1176 return true;
1180 off_t
1181 ServerPicture::DataLength() const
1183 if (fData == NULL)
1184 return 0;
1185 off_t size;
1186 fData->GetSize(&size);
1187 return size;
1191 status_t
1192 ServerPicture::ImportData(BPrivate::LinkReceiver& link)
1194 int32 size = 0;
1195 link.Read<int32>(&size);
1197 off_t oldPosition = fData->Position();
1198 fData->Seek(0, SEEK_SET);
1200 status_t status = B_NO_MEMORY;
1201 char* buffer = new(std::nothrow) char[size];
1202 if (buffer) {
1203 status = B_OK;
1204 ssize_t read = link.Read(buffer, size);
1205 if (read < B_OK || fData->Write(buffer, size) < B_OK)
1206 status = B_ERROR;
1207 delete [] buffer;
1210 fData->Seek(oldPosition, SEEK_SET);
1211 return status;
1215 status_t
1216 ServerPicture::ExportData(BPrivate::PortLink& link)
1218 link.StartMessage(B_OK);
1220 off_t oldPosition = fData->Position();
1221 fData->Seek(0, SEEK_SET);
1223 int32 subPicturesCount = 0;
1224 if (fPictures != NULL)
1225 subPicturesCount = fPictures->CountItems();
1226 link.Attach<int32>(subPicturesCount);
1227 if (subPicturesCount > 0) {
1228 for (int32 i = 0; i < subPicturesCount; i++) {
1229 ServerPicture* subPicture = fPictures->ItemAt(i);
1230 link.Attach<int32>(subPicture->Token());
1234 off_t size = 0;
1235 fData->GetSize(&size);
1236 link.Attach<int32>((int32)size);
1238 status_t status = B_NO_MEMORY;
1239 char* buffer = new(std::nothrow) char[size];
1240 if (buffer) {
1241 status = B_OK;
1242 ssize_t read = fData->Read(buffer, size);
1243 if (read < B_OK || link.Attach(buffer, read) < B_OK)
1244 status = B_ERROR;
1245 delete [] buffer;
1248 if (status != B_OK) {
1249 link.CancelMessage();
1250 link.StartMessage(B_ERROR);
1253 fData->Seek(oldPosition, SEEK_SET);
1254 return status;