Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/tools/FreeLineTool.cpp
Warning:line 97, column 10
Potential leak of memory pointed to by 'drawer'

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 FreeLineTool.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/tools/FreeLineTool.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 "FreeLineTool.h"
14
15#include "BitmapDrawer.h"
16#include "BitmapUtilities.h"
17#include "Cursors.h"
18#include "CoordinateQueue.h"
19#include "Image.h"
20#include "ImageView.h"
21#include "NumberSliderControl.h"
22#include "PaintApplication.h"
23#include "PixelOperations.h"
24#include "ToolScript.h"
25#include "UtilityClasses.h"
26
27
28#include <Catalog.h>
29#include <GridLayoutBuilder.h>
30#include <Layout.h>
31#include <Window.h>
32
33
34#undef B_TRANSLATION_CONTEXT"Tools"
35#define B_TRANSLATION_CONTEXT"Tools" "Tools"
36
37
38using ArtPaint::Interface::NumberSliderControl;
39
40
41FreeLineTool::FreeLineTool()
42 : DrawingTool(B_TRANSLATE("Freehand line tool")BLocaleRoster::Default()->GetCatalog()->GetString(("Freehand line tool"
), "Tools")
,
43 FREE_LINE_TOOL)
44{
45 fOptions = SIZE_OPTION;
46 fOptionsCount = 1;
47
48 SetOption(SIZE_OPTION, 1);
49}
50
51
52FreeLineTool::~FreeLineTool()
53{
54}
55
56
57ToolScript*
58FreeLineTool::UseTool(ImageView* view, uint32 buttons, BPoint point, BPoint)
59{
60 // Wait for the last_updated_region to become empty
61 while (LastUpdatedRect().IsValid())
1
Loop condition is false. Execution continues on line 64
62 snooze(50000);
63
64 coordinate_queue = new CoordinateQueue();
65 image_view = view;
66 thread_id coordinate_reader = spawn_thread(CoordinateReader,
67 "read coordinates", B_NORMAL_PRIORITY10, this);
68 resume_thread(coordinate_reader);
69 reading_coordinates = true;
70 ToolScript *the_script = new ToolScript(Type(), fToolSettings,
71 ((PaintApplication*)be_app)->Color(true));
72
73 BBitmap* buffer = view->ReturnImage()->ReturnActiveBitmap();
74 BBitmap* srcBuffer = new (std::nothrow) BBitmap(buffer);
75 if (srcBuffer == NULL__null)
2
Assuming 'srcBuffer' is not equal to NULL
3
Taking false branch
76 return NULL__null;
77 BBitmap* tmpBuffer = new (std::nothrow) BBitmap(buffer);
78 if (tmpBuffer == NULL__null) {
4
Assuming 'tmpBuffer' is not equal to NULL
5
Taking false branch
79 delete srcBuffer;
80 return NULL__null;
81 }
82 union color_conversion clear_color;
83 clear_color.word = 0xFFFFFFFF;
84 clear_color.bytes[3] = 0x01;
85
86 BitmapUtilities::ClearBitmap(tmpBuffer, clear_color.word);
87
88 Selection *selection = view->GetSelection();
89// BView *buffer_view = view->getBufferView();
90 BitmapDrawer *drawer = new BitmapDrawer(tmpBuffer);
6
Memory is allocated
91 rgb_color new_color;
92 uint32 new_color_bgra;
93// int32 original_mouse_speed;
94// get_mouse_speed(&original_mouse_speed);
95
96 if (buffer == NULL__null) {
7
Assuming 'buffer' is equal to NULL
8
Taking true branch
97 delete the_script;
9
Potential leak of memory pointed to by 'drawer'
98 delete srcBuffer;
99 delete tmpBuffer;
100
101 return NULL__null;
102 }
103 BPoint prev_point;
104
105 prev_point = point;
106 BRect updated_rect;
107 status_t status_of_read;
108 int diameter = fToolSettings.size;
109 if ((diameter%2) == 0)
110 diameter++;
111
112 new_color = ((PaintApplication*)be_app)->Color(true);
113 new_color_bgra = RGBColorToBGRA(new_color);
114 if (diameter != 1)
115 drawer->DrawCircle(prev_point, diameter / 2, new_color_bgra,
116 true, false, selection, NULL__null);
117 else
118 drawer->DrawHairLine(prev_point, point, new_color_bgra,
119 false, selection, NULL__null);
120
121 // This makes sure that the view is updated even if just one point is drawn
122 updated_rect.left = min_c(point.x-diameter/2,prev_point.x-diameter/2)((point.x-diameter/2)>(prev_point.x-diameter/2)?(prev_point
.x-diameter/2):(point.x-diameter/2))
;
123 updated_rect.top = min_c(point.y-diameter/2,prev_point.y-diameter/2)((point.y-diameter/2)>(prev_point.y-diameter/2)?(prev_point
.y-diameter/2):(point.y-diameter/2))
;
124 updated_rect.right = max_c(point.x+diameter/2,prev_point.x+diameter/2)((point.x+diameter/2)>(prev_point.x+diameter/2)?(point.x+diameter
/2):(prev_point.x+diameter/2))
;
125 updated_rect.bottom = max_c(point.y+diameter/2,prev_point.y+diameter/2)((point.y+diameter/2)>(prev_point.y+diameter/2)?(point.y+diameter
/2):(prev_point.y+diameter/2))
;
126
127 // We should do the composite picture and re-draw the window in
128 // a separate thread.
129 view->ReturnImage()->Render(updated_rect);
130 view->Window()->Lock();
131 BitmapUtilities::CompositeBitmapOnSource(buffer, srcBuffer,
132 tmpBuffer, updated_rect);
133 // We have to use Draw, because Invalidate causes flickering by erasing
134 // the area before calling Draw.
135 view->Draw(view->convertBitmapRectToView(updated_rect));
136 view->UpdateImage(updated_rect);
137 view->Sync();
138 view->Window()->Unlock();
139
140 SetLastUpdatedRect(updated_rect);
141 the_script->AddPoint(point);
142 while (((status_of_read = coordinate_queue->Get(point)) == B_OK((int)0))
143 || (reading_coordinates == true)) {
144 if ( (status_of_read == B_OK((int)0)) && (prev_point != point) ) {
145 the_script->AddPoint(point);
146// if (modifiers() & B_LEFT_CONTROL_KEY) {
147// set_mouse_speed(0);
148// }
149// else {
150// set_mouse_speed(original_mouse_speed);
151// }
152 // first set the color
153 new_color = ((PaintApplication*)be_app)->Color(true);
154 new_color_bgra = RGBColorToBGRA(new_color);
155
156 diameter = fToolSettings.size;
157 if ((diameter%2) == 0)
158 diameter++;
159
160 if (diameter != 1) {
161 drawer->DrawCircle(point,diameter / 2, new_color_bgra,
162 true, false, selection, NULL__null);
163 drawer->DrawLine(prev_point,point, new_color_bgra, diameter,
164 false, selection, NULL__null);
165 }
166 else
167 drawer->DrawHairLine(prev_point, point, new_color_bgra,
168 false, selection);
169
170 updated_rect.left = min_c(point.x-diameter/2-1,prev_point.x-diameter/2-1)((point.x-diameter/2-1)>(prev_point.x-diameter/2-1)?(prev_point
.x-diameter/2-1):(point.x-diameter/2-1))
;
171 updated_rect.top = min_c(point.y-diameter/2-1,prev_point.y-diameter/2-1)((point.y-diameter/2-1)>(prev_point.y-diameter/2-1)?(prev_point
.y-diameter/2-1):(point.y-diameter/2-1))
;
172 updated_rect.right = max_c(point.x+diameter/2+1,prev_point.x+diameter/2+1)((point.x+diameter/2+1)>(prev_point.x+diameter/2+1)?(point
.x+diameter/2+1):(prev_point.x+diameter/2+1))
;
173 updated_rect.bottom = max_c(point.y+diameter/2+1,prev_point.y+diameter/2+1)((point.y+diameter/2+1)>(prev_point.y+diameter/2+1)?(point
.y+diameter/2+1):(prev_point.y+diameter/2+1))
;
174
175 SetLastUpdatedRect(LastUpdatedRect() | updated_rect);
176
177 // We should do the composite picture and re-draw the window in
178 // a separate thread.
179 view->Window()->Lock();
180 BitmapUtilities::CompositeBitmapOnSource(buffer, srcBuffer,
181 tmpBuffer, updated_rect);
182 view->UpdateImage(updated_rect);
183 view->Sync();
184 view->Window()->Unlock();
185 prev_point = point;
186 }
187 else
188 snooze(20 * 1000);
189 }
190
191 delete srcBuffer;
192 delete tmpBuffer;
193
194 delete drawer;
195 delete coordinate_queue;
196 return the_script;
197}
198
199
200int32
201FreeLineTool::UseToolWithScript(ToolScript*,BBitmap*)
202{
203 return B_OK((int)0);
204}
205
206
207BView*
208FreeLineTool::ConfigView()
209{
210 return new FreeLineToolConfigView(this);
211}
212
213
214const void*
215FreeLineTool::ToolCursor() const
216{
217 return HS_FREE_LINE_CURSOR;
218}
219
220
221const char*
222FreeLineTool::HelpString(bool isInUse) const
223{
224 return (isInUse
225 ? B_TRANSLATE("Drawing a freehand line.")BLocaleRoster::Default()->GetCatalog()->GetString(("Drawing a freehand line."
), "Tools")
226 : B_TRANSLATE("Click to draw a freehand line.")BLocaleRoster::Default()->GetCatalog()->GetString(("Click to draw a freehand line."
), "Tools")
);
227}
228
229
230int32
231FreeLineTool::CoordinateReader(void *data)
232{
233 FreeLineTool *this_pointer = (FreeLineTool*)data;
234 return this_pointer->read_coordinates();
235}
236
237
238int32
239FreeLineTool::read_coordinates()
240{
241 reading_coordinates = true;
242 uint32 buttons;
243 BPoint point,prev_point;
244 BPoint view_point;
245 image_view->Window()->Lock();
246 image_view->getCoords(&point,&buttons,&view_point);
247 image_view->MovePenTo(view_point);
248 image_view->Window()->Unlock();
249 prev_point = point + BPoint(1,1);
250
251 while (buttons) {
252 image_view->Window()->Lock();
253 if (point != prev_point) {
254 coordinate_queue->Put(point);
255 image_view->StrokeLine(view_point);
256 prev_point = point;
257 }
258 image_view->getCoords(&point,&buttons,&view_point);
259 image_view->Window()->Unlock();
260 snooze(20 * 1000);
261 }
262
263 reading_coordinates = false;
264 return B_OK((int)0);
265}
266
267
268// #pragma mark -- FreeLineToolConfigView
269
270
271FreeLineToolConfigView::FreeLineToolConfigView(DrawingTool* tool)
272 : DrawingToolConfigView(tool)
273{
274 if (BLayout* layout = GetLayout()) {
275 BMessage* message = new BMessage(OPTION_CHANGED);
276 message->AddInt32("option", SIZE_OPTION);
277 message->AddInt32("value", tool->GetCurrentValue(SIZE_OPTION));
278
279 fLineSize =
280 new NumberSliderControl(B_TRANSLATE("Width:")BLocaleRoster::Default()->GetCatalog()->GetString(("Width:"
), "Tools")
,
281 "1", message, 1, 100, false);
282
283 BGridLayout* lineSizeLayout = LayoutSliderGrid(fLineSize);
284
285 layout->AddView(lineSizeLayout->View());
286 }
287}
288
289
290void
291FreeLineToolConfigView::AttachedToWindow()
292{
293 DrawingToolConfigView::AttachedToWindow();
294
295 fLineSize->SetTarget(this);
296}