Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/viewmanipulators/CropManipulator.cpp
Warning:line 402, column 2
Potential leak of memory pointed to by 'settings'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-haiku -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CropManipulator.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /boot/system/lib/clang/12.0.1 -iquote ./ -iquote artpaint/ -iquote artpaint/Utilities/ -iquote artpaint/application/ -iquote artpaint/controls/ -iquote artpaint/layers/ -iquote artpaint/paintwindow/ -iquote artpaint/tools/ -iquote artpaint/viewmanipulators/ -iquote artpaint/windows/ -iquote objects_artpaint/ -isystem /boot/system/develop/headers/private/interface -internal-isystem /system/develop/headers/c++ -internal-isystem /system/develop/headers/c++/x86_64-unknown-haiku -internal-isystem /system/develop/headers/c++/backward -O3 -fdeprecated-macro -fdebug-compilation-dir /boot/home/HaikuArchives/ArtPaint -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2022-06-19-103017-1294-1 -x c++ artpaint/viewmanipulators/CropManipulator.cpp
1/*
2 * Copyright 2003, Heikki Suhonen
3 * Copyright 2009, Karsten Heimrich
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 * Heikki Suhonen <heikki.suhonen@gmail.com>
8 * Karsten Heimrich <host.haiku@gmx.de>
9 * Dale Cieslak <dcieslak@yahoo.com>
10 *
11 */
12
13#include "CropManipulator.h"
14
15#include "MessageConstants.h"
16#include "NumberControl.h"
17
18
19#include <Bitmap.h>
20#include <Catalog.h>
21#include <GroupLayout.h>
22#include <GroupLayoutBuilder.h>
23#include <StatusBar.h>
24#include <Window.h>
25
26
27#include <new>
28
29
30#undef B_TRANSLATION_CONTEXT"Manipulators"
31#define B_TRANSLATION_CONTEXT"Manipulators" "Manipulators"
32
33
34using ArtPaint::Interface::NumberControl;
35
36
37CropManipulator::CropManipulator(BBitmap *bm)
38 : WindowGUIManipulator()
39{
40 settings = new CropManipulatorSettings();
41 config_view = NULL__null;
42
43 min_x = 0;
44 max_x = 0;
45 min_y = 0;
46 max_y = 0;
47
48 if (bm != NULL__null) {
49 BRect rect = bm->Bounds();
50 settings->left = min_x = rect.left;
51 settings->right = max_x = rect.right;
52 settings->top = min_y = rect.top;
53 settings->bottom = max_y = rect.bottom;
54 }
55}
56
57
58
59CropManipulator::~CropManipulator()
60{
61 if (config_view != NULL__null) {
62 config_view->RemoveSelf();
63 delete config_view;
64 }
65
66 delete settings;
67}
68
69
70void CropManipulator::MouseDown(BPoint point,uint32,BView*,bool first)
71{
72 previous_left = settings->left;
73 previous_right = settings->right;
74 previous_top = settings->top;
75 previous_bottom = settings->bottom;
76
77 point.x = floor(point.x);
78 point.y = floor(point.y);
79
80 if (first == TRUE1) {
81 // Here we select which grabbles to move
82 move_left = move_right = move_top = move_bottom = FALSE0;
83 if (fabs(point.x - settings->left) < 50)
84 if (fabs(point.x-settings->left)<fabs(point.x-(settings->left+(settings->right-settings->left)/2)))
85 move_left = TRUE1;
86 if (fabs(point.x - settings->right) < 50)
87 if (fabs(point.x-settings->right)<fabs(point.x-(settings->left+(settings->right-settings->left)/2)))
88 move_right = TRUE1;
89 if ((move_left == TRUE1) && (move_right == TRUE1)) {
90 if (fabs(point.x - settings->left) > fabs(point.x - settings->right))
91 move_left = FALSE0;
92 else
93 move_right = FALSE0;
94 }
95
96 if (fabs(point.y - settings->top) < 50)
97 if (fabs(point.y-settings->top)<fabs(point.y-(settings->top+(settings->bottom-settings->top)/2)))
98 move_top = TRUE1;
99 if (fabs(point.y - settings->bottom) < 50)
100 if (fabs(point.y-settings->bottom)<fabs(point.y-(settings->top+(settings->bottom-settings->top)/2)))
101 move_bottom = TRUE1;
102 if ((move_top == TRUE1) && (move_bottom == TRUE1)) {
103 if (fabs(point.y - settings->top) > fabs(point.y - settings->bottom))
104 move_top = FALSE0;
105 else
106 move_bottom = FALSE0;
107 }
108
109
110 if ((move_left == FALSE0) && (move_top == FALSE0) && (move_right == FALSE0) && (move_bottom == FALSE0))
111 move_all = TRUE1;
112 else
113 move_all = FALSE0;
114
115
116 }
117 else {
118 if (move_left == TRUE1)
119 settings->left = min_c(point.x,settings->right)((point.x)>(settings->right)?(settings->right):(point
.x))
;
120 if (move_right == TRUE1)
121 settings->right = max_c(settings->left,point.x)((settings->left)>(point.x)?(settings->left):(point.
x))
;
122
123 if (move_top == TRUE1)
124 settings->top = min_c(point.y,settings->bottom)((point.y)>(settings->bottom)?(settings->bottom):(point
.y))
;
125 if (move_bottom == TRUE1)
126 settings->bottom = max_c(settings->top,point.y)((settings->top)>(point.y)?(settings->top):(point.y)
)
;
127
128
129 if (move_all == TRUE1) {
130 float width = settings->right - settings->left;
131 float height = settings->bottom - settings->top;
132
133 float new_left,new_top,new_right,new_bottom;
134
135 new_left = point.x-width/2;
136 new_right = new_left + width;
137 new_top = point.y-height/2;
138 new_bottom = new_top + height;
139
140 settings->left = new_left;
141 settings->top = new_top;
142 settings->right = new_right;
143 settings->bottom = new_bottom;
144
145 }
146 }
147
148 if ((previous_left != settings->left) || (previous_right != settings->right) ||
149 (previous_top != settings->top) || (previous_bottom != settings->bottom))
150 if (config_view != NULL__null)
151 config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom);
152}
153
154
155BRegion CropManipulator::Draw(BView *view,float mag_scale)
156{
157 int32 DRAGGER_SIZE = 5;
158 // Draw all the data that needs to be drawn
159 BRect bounds = BRect(mag_scale*settings->left,mag_scale*settings->top,mag_scale*(settings->right+1)-1,mag_scale*(settings->bottom+1)-1);
160 bounds.left = floor(bounds.left);
161 bounds.top = floor(bounds.top);
162 bounds.right = ceil(bounds.right);
163 bounds.bottom = ceil(bounds.bottom);
164
165 bool draw_draggers = FALSE0;
166 BRect dragger_rect = BRect(0,0,DRAGGER_SIZE-1,DRAGGER_SIZE-1);
167 float f_bottom = bounds.bottom;
168 float f_top = bounds.top;
169 float f_left = bounds.left;
170 float f_right = bounds.right;
171
172 if ( (f_bottom-f_top> 3*DRAGGER_SIZE+10) && (f_right-f_left > 3*DRAGGER_SIZE+10) ) {
173 draw_draggers = TRUE1;
174 }
175 view->StrokeRect(bounds,B_MIXED_COLORS);
176 if (draw_draggers == TRUE1) {
177 dragger_rect.OffsetTo(bounds.LeftTop());
178 view->FillRect(dragger_rect,B_MIXED_COLORS);
179
180 dragger_rect.OffsetTo(bounds.LeftTop()+BPoint((f_right-f_left)/2-DRAGGER_SIZE/2,0));
181 view->FillRect(dragger_rect,B_MIXED_COLORS);
182
183 dragger_rect.OffsetTo(bounds.LeftTop()+BPoint(f_right-f_left-DRAGGER_SIZE+1,0));
184 view->FillRect(dragger_rect,B_MIXED_COLORS);
185
186 dragger_rect.OffsetTo(bounds.LeftTop()+BPoint(0,(f_bottom-f_top)/2-DRAGGER_SIZE/2));
187 view->FillRect(dragger_rect,B_MIXED_COLORS);
188
189 dragger_rect.OffsetTo(bounds.RightTop()+BPoint(-DRAGGER_SIZE+1,(f_bottom-f_top)/2-DRAGGER_SIZE/2));
190 view->FillRect(dragger_rect,B_MIXED_COLORS);
191
192 dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint(0,-DRAGGER_SIZE+1));
193 view->FillRect(dragger_rect,B_MIXED_COLORS);
194
195 dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint((f_right-f_left)/2-DRAGGER_SIZE/2,-DRAGGER_SIZE+1));
196 view->FillRect(dragger_rect,B_MIXED_COLORS);
197
198 dragger_rect.OffsetTo(bounds.LeftBottom()+BPoint(f_right-f_left-DRAGGER_SIZE+1,-DRAGGER_SIZE+1));
199 view->FillRect(dragger_rect,B_MIXED_COLORS);
200 }
201
202 BRegion updated_region;
203
204 bounds.InsetBy(-1,-1);
205 updated_region.Set(bounds);
206 bounds.InsetBy(DRAGGER_SIZE+2,DRAGGER_SIZE+2);
207 updated_region.Exclude(bounds);
208
209 return updated_region;
210}
211
212
213
214BBitmap* CropManipulator::ManipulateBitmap(ManipulatorSettings *set,
215 BBitmap *original, Selection*, BStatusBar *status_bar)
216{
217 CropManipulatorSettings* new_settings =
218 dynamic_cast<CropManipulatorSettings*> (set);
219
220 if (new_settings == NULL__null)
221 return NULL__null;
222
223 float left = new_settings->left;
224 float right = new_settings->right;
225 float top = new_settings->top;
226 float bottom = new_settings->bottom;
227
228 if ( ((right-left) == original->Bounds().Width()) && ((bottom-top) == original->Bounds().Height()))
229 return NULL__null;
230
231 // Create a new bitmap here and copy the appropriate part from original.
232 // Return the new bitmap.
233 BBitmap *new_bitmap;
234 new_bitmap = new BBitmap(BRect(0,0,right-left,bottom-top),B_RGB_32_BIT);
235 if (new_bitmap->IsValid() == FALSE0)
236 throw std::bad_alloc();
237
238 uint32 *orig_bits = (uint32*)original->Bits();
239 uint32 *new_bits = (uint32*)new_bitmap->Bits();
240 int32 original_bpr = original->BytesPerRow()/4;
241 float height = bottom-top+1;
242 BMessage progress_message = BMessage(B_UPDATE_STATUS_BAR);
243 progress_message.AddFloat("delta",0.0);
244
245 union {
246 uint8 bytes[4];
247 uint32 word;
248 } background;
249
250 background.bytes[0] = 0xFF;
251 background.bytes[1] = 0xFF;
252 background.bytes[2] = 0xFF;
253 background.bytes[3] = 0x00;
254
255 for (int32 y=(int32)top;y<=bottom;y++) {
256 for (int32 x=(int32)left;x<=right;x++) {
257 if ((x>=0) && (y>=0) && (x<=original->Bounds().right) && (y<=original->Bounds().bottom))
258 *new_bits++ = *(orig_bits + x +y*original_bpr);
259 else
260 *new_bits++ = background.word;
261 }
262 if ((y%10 == 0) && (status_bar != NULL__null)) {
263 progress_message.ReplaceFloat("delta",(100.0)/height*10.0);
264 status_bar->Window()->PostMessage(&progress_message,status_bar);
265 }
266 }
267
268 return new_bitmap;
269}
270
271int32 CropManipulator::PreviewBitmap(Selection*,bool,BRegion*)
272{
273 if ((previous_left == settings->left) && (previous_right == settings->right) &&
274 (previous_top == settings->top) && (previous_bottom == settings->bottom))
275 return DRAW_NOTHING;
276 else
277 return DRAW_ONLY_GUI;
278}
279
280void CropManipulator::SetPreviewBitmap(BBitmap *bm)
281{
282 if (bm != NULL__null) {
283 BRect rect = bm->Bounds();
284 settings->left = min_x = rect.left;
285 settings->right = max_x = rect.right;
286 settings->top = min_y = rect.top;
287 settings->bottom = max_y = rect.bottom;
288 }
289 else {
290 settings->left = min_x = 0;
291 settings->right = max_x = 0;
292 settings->top = min_y = 0;
293 settings->bottom = max_y = 0;
294 }
295
296 if (config_view != NULL__null) {
297 config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom);
298 }
299}
300
301void CropManipulator::SetValues(float x1, float x2, float y1, float y2)
302{
303 previous_left = settings->left;
304 previous_right = settings->right;
305 previous_top = settings->top;
306 previous_bottom = settings->bottom;
307
308 settings->left = x1;
309 settings->right = x2;
310 settings->top = y1;
311 settings->bottom = y2;
312
313 settings->left = min_c(settings->left,settings->right)((settings->left)>(settings->right)?(settings->right
):(settings->left))
;
314 settings->right = max_c(settings->left,settings->right)((settings->left)>(settings->right)?(settings->left
):(settings->right))
;
315
316 settings->top = min_c(settings->top,settings->bottom)((settings->top)>(settings->bottom)?(settings->bottom
):(settings->top))
;
317 settings->bottom = max_c(settings->top,settings->bottom)((settings->top)>(settings->bottom)?(settings->top
):(settings->bottom))
;
318
319 if (config_view != NULL__null) {
320 config_view->SetValues(settings->left,settings->right,settings->top,settings->bottom);
321 }
322}
323
324
325ManipulatorSettings*
326CropManipulator::ReturnSettings()
327{
328 return new CropManipulatorSettings(settings);
3
Memory is allocated
329}
330
331
332BView*
333CropManipulator::MakeConfigurationView(const BMessenger& target)
334{
335 config_view = new CropManipulatorView(this, target);
1
Calling constructor for 'CropManipulatorView'
336 config_view->SetValues(settings->left, settings->right, settings->top,
337 settings->bottom);
338 return config_view;
339}
340
341
342const char*
343CropManipulator::ReturnName()
344{
345 return B_TRANSLATE("Crop" B_UTF8_ELLIPSIS)BLocaleRoster::Default()->GetCatalog()->GetString(("Crop"
"\xE2\x80\xA6"), "Manipulators")
;
346}
347
348
349const char*
350CropManipulator::ReturnHelpString()
351{
352 return B_TRANSLATE("Use the handles or number-fields to set the new borders.")BLocaleRoster::Default()->GetCatalog()->GetString(("Use the handles or number-fields to set the new borders."
), "Manipulators")
;
353}
354
355
356// #pragma mark -- CropManipulatorView
357
358
359CropManipulatorView::CropManipulatorView(CropManipulator* manipulator,
360 const BMessenger& target)
361 : WindowGUIManipulatorView()
362 , fTarget(target)
363 , fManipulator(manipulator)
364{
365 fTopCrop = new NumberControl(B_TRANSLATE("Top:")BLocaleRoster::Default()->GetCatalog()->GetString(("Top:"
), "Manipulators")
, "",
366 new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5, true);
367 fLeftCrop = new NumberControl(B_TRANSLATE("Left:")BLocaleRoster::Default()->GetCatalog()->GetString(("Left:"
), "Manipulators")
, "",
368 new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5, true);
369 fRightCrop = new NumberControl(B_TRANSLATE("Right:")BLocaleRoster::Default()->GetCatalog()->GetString(("Right:"
), "Manipulators")
,
370 "", new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5);
371 fBottomCrop = new NumberControl(B_TRANSLATE("Bottom:")BLocaleRoster::Default()->GetCatalog()->GetString(("Bottom:"
), "Manipulators")
,
372 "", new BMessage(HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi'), 5);
373
374 SetLayout(new BGroupLayout(B_HORIZONTAL));
375 AddChild(BGroupLayoutBuilder(B_VERTICAL, 5.0)
376 .AddGroup(B_HORIZONTAL)
377 .AddGlue()
378 .Add(fTopCrop)
379 .AddGlue()
380 .End()
381 .AddGroup(B_HORIZONTAL)
382 .AddGlue()
383 .Add(fLeftCrop)
384 .AddGlue()
385 .AddStrut(80.0)
386 .AddGlue()
387 .Add(fRightCrop)
388 .AddGlue()
389 .End()
390 .AddGroup(B_HORIZONTAL)
391 .AddGlue()
392 .Add(fBottomCrop)
393 .AddGlue()
394 .End()
395 );
396
397 CropManipulatorSettings* settings
398 = (CropManipulatorSettings*)manipulator->ReturnSettings();
2
Calling 'CropManipulator::ReturnSettings'
4
Returned allocated memory
399 fTopCrop->SetValue(settings->top);
400 fLeftCrop->SetValue(settings->left);
401 fRightCrop->SetValue(settings->right);
402 fBottomCrop->SetValue(settings->bottom);
5
Potential leak of memory pointed to by 'settings'
403}
404
405
406void
407CropManipulatorView::AttachedToWindow()
408{
409 fTopCrop->SetTarget(this);
410 fTopCrop->MakeFocus(true);
411
412 fLeftCrop->SetTarget(this);
413 fRightCrop->SetTarget(this);
414 fBottomCrop->SetTarget(this);
415
416 WindowGUIManipulatorView::AttachedToWindow();
417}
418
419
420void
421CropManipulatorView::SetValues(float x1, float x2, float y1, float y2)
422{
423 BWindow* window = Window();
424 if (window && window->Lock()) {
425 left = x1;
426 right = x2;
427 top = y1;
428 bottom = y2;
429
430 if (left != fLeftCrop->Value())
431 fLeftCrop->SetValue(int32(left));
432
433 if (right != fRightCrop->Value())
434 fRightCrop->SetValue(int32(right));
435
436 if (top != fTopCrop->Value())
437 fTopCrop->SetValue(int32(top));
438
439 if (bottom != fBottomCrop->Value())
440 fBottomCrop->SetValue(int32(bottom));
441
442 window->Unlock();
443 }
444}
445
446
447void
448CropManipulatorView::MessageReceived(BMessage *message)
449{
450 switch (message->what) {
451 case HS_MANIPULATOR_ADJUSTING_FINISHED'Mafi': {
452 fManipulator->SetValues(fLeftCrop->Value(),
453 fRightCrop->Value(), fTopCrop->Value(),
454 fBottomCrop->Value());
455 fTarget.SendMessage(message);
456 } break;
457
458 default: {
459 WindowGUIManipulatorView::MessageReceived(message);
460 } break;
461 }
462}