vfs: check userland buffers before reading them.
[haiku.git] / src / servers / app / Canvas.cpp
blob881eaaabce1db6f09a7ea65c7065327ddacb5552
1 /*
2 * Copyright (c) 2001-2015, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Adi Oanca <adioanca@gmail.com>
8 * Axel Dörfler, axeld@pinc-software.de
9 * Stephan Aßmus <superstippi@gmx.de>
10 * Marcus Overhagen <marcus@overhagen.de>
11 * Adrien Destugues <pulkomandy@pulkomandy.tk
12 * Julian Harnath <julian.harnath@rwth-aachen.de>
16 #include "Canvas.h"
18 #include <new>
20 #include <Region.h>
22 #include "AlphaMask.h"
23 #include "DrawingEngine.h"
24 #include "DrawState.h"
25 #include "Layer.h"
28 #if __GNUC__ >= 3
29 # define GCC_2_NRV(x)
30 // GCC >= 3.1 doesn't need it anymore
31 #else
32 # define GCC_2_NRV(x) return x;
33 // GCC 2 named return value syntax
34 // see http://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_5.html#SEC106
35 #endif
38 Canvas::Canvas()
40 fDrawState(new(std::nothrow) DrawState())
45 Canvas::Canvas(const DrawState& state)
47 fDrawState(new(std::nothrow) DrawState(state))
52 Canvas::~Canvas()
57 status_t
58 Canvas::InitCheck() const
60 if (fDrawState == NULL)
61 return B_NO_MEMORY;
63 return B_OK;
67 void
68 Canvas::PushState()
70 DrawState* newState = fDrawState->PushState();
71 if (newState)
72 fDrawState = newState;
76 void
77 Canvas::PopState()
79 if (fDrawState->PreviousState() == NULL)
80 return;
82 bool rebuildClipping = fDrawState->HasAdditionalClipping();
84 fDrawState = fDrawState->PopState();
86 // rebuild clipping
87 // (the clipping from the popped state is not effective anymore)
88 if (rebuildClipping)
89 RebuildClipping(false);
93 void
94 Canvas::SetDrawState(DrawState* newState)
96 fDrawState = newState;
100 void
101 Canvas::SetDrawingOrigin(BPoint origin)
103 fDrawState->SetOrigin(origin);
105 // rebuild clipping
106 if (fDrawState->HasClipping())
107 RebuildClipping(false);
111 BPoint
112 Canvas::DrawingOrigin() const
114 BPoint origin(fDrawState->Origin());
115 float scale = Scale();
117 origin.x *= scale;
118 origin.y *= scale;
120 return origin;
124 void
125 Canvas::SetScale(float scale)
127 fDrawState->SetScale(scale);
129 // rebuild clipping
130 if (fDrawState->HasClipping())
131 RebuildClipping(false);
135 float
136 Canvas::Scale() const
138 return fDrawState->Scale();
142 void
143 Canvas::SetUserClipping(const BRegion* region)
145 fDrawState->SetClippingRegion(region);
147 // rebuild clipping (for just this canvas)
148 RebuildClipping(false);
152 bool
153 Canvas::ClipToRect(BRect rect, bool inverse)
155 bool needDrawStateUpdate = fDrawState->ClipToRect(rect, inverse);
156 RebuildClipping(false);
157 return needDrawStateUpdate;
161 void
162 Canvas::ClipToShape(shape_data* shape, bool inverse)
164 fDrawState->ClipToShape(shape, inverse);
168 void
169 Canvas::SetAlphaMask(AlphaMask* mask)
171 fDrawState->SetAlphaMask(mask);
175 AlphaMask*
176 Canvas::GetAlphaMask() const
178 return fDrawState->GetAlphaMask();
182 SimpleTransform
183 Canvas::LocalToScreenTransform() const GCC_2_NRV(transform)
185 #if __GNUC__ >= 3
186 SimpleTransform transform;
187 #endif
188 _LocalToScreenTransform(transform);
189 return transform;
193 SimpleTransform
194 Canvas::ScreenToLocalTransform() const GCC_2_NRV(transform)
196 #if __GNUC__ >= 3
197 SimpleTransform transform;
198 #endif
199 _ScreenToLocalTransform(transform);
200 return transform;
204 SimpleTransform
205 Canvas::PenToScreenTransform() const GCC_2_NRV(transform)
207 #if __GNUC__ >= 3
208 SimpleTransform transform;
209 #endif
210 fDrawState->Transform(transform);
211 _LocalToScreenTransform(transform);
212 return transform;
216 SimpleTransform
217 Canvas::PenToLocalTransform() const GCC_2_NRV(transform)
219 #if __GNUC__ >= 3
220 SimpleTransform transform;
221 #endif
222 fDrawState->Transform(transform);
223 return transform;
227 SimpleTransform
228 Canvas::ScreenToPenTransform() const GCC_2_NRV(transform)
230 #if __GNUC__ >= 3
231 SimpleTransform transform;
232 #endif
233 _ScreenToLocalTransform(transform);
234 fDrawState->InverseTransform(transform);
235 return transform;
239 void
240 Canvas::BlendLayer(Layer* layer)
242 if (layer->Opacity() == 255) {
243 layer->Play(this);
244 layer->ReleaseReference();
245 return;
248 UtilityBitmap* layerBitmap = layer->RenderToBitmap(this);
249 if (layerBitmap == NULL)
250 return;
252 BRect destination = layerBitmap->Bounds();
253 destination.OffsetBy(layer->LeftTopOffset());
254 LocalToScreenTransform().Apply(&destination);
256 PushState();
258 fDrawState->SetDrawingMode(B_OP_ALPHA);
259 fDrawState->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
260 fDrawState->SetTransformEnabled(false);
262 AlphaMask* mask = new(std::nothrow) UniformAlphaMask(layer->Opacity());
263 if (mask == NULL) {
264 layerBitmap->ReleaseReference();
265 layer->ReleaseReference();
266 return;
269 SetAlphaMask(mask);
270 mask->ReleaseReference();
271 ResyncDrawState();
273 GetDrawingEngine()->DrawBitmap(layerBitmap, layerBitmap->Bounds(),
274 destination, 0);
276 fDrawState->SetTransformEnabled(true);
278 PopState();
279 ResyncDrawState();
281 layerBitmap->ReleaseReference();
282 layer->ReleaseReference();
286 // #pragma mark - OffscreenCanvas
289 OffscreenCanvas::OffscreenCanvas(DrawingEngine* engine,
290 const DrawState& state, const IntRect& bounds)
292 Canvas(state),
293 fDrawingEngine(engine),
294 fBounds(bounds)
296 ResyncDrawState();
300 OffscreenCanvas::~OffscreenCanvas()
302 delete fDrawState;
306 void
307 OffscreenCanvas::ResyncDrawState()
309 fDrawingEngine->SetDrawState(fDrawState);
313 void
314 OffscreenCanvas::UpdateCurrentDrawingRegion()
316 if (fDrawState->HasClipping()) {
317 fDrawState->GetCombinedClippingRegion(&fCurrentDrawingRegion);
318 fDrawingEngine->ConstrainClippingRegion(&fCurrentDrawingRegion);
323 IntRect
324 OffscreenCanvas::Bounds() const
326 return fBounds;