Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/tools/StraightLineTool.cpp
Warning:line 193, column 19
Called C++ object pointer is null

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 StraightLineTool.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/StraightLineTool.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 "StraightLineTool.h"
14
15#include "BitmapDrawer.h"
16#include "Cursors.h"
17#include "HSPolygon.h"
18#include "Image.h"
19#include "ImageView.h"
20#include "NumberSliderControl.h"
21#include "PaintApplication.h"
22#include "Selection.h"
23#include "ToolScript.h"
24#include "UtilityClasses.h"
25
26
27#include <Catalog.h>
28#include <CheckBox.h>
29#include <GridLayoutBuilder.h>
30#include <GroupLayoutBuilder.h>
31#include <SeparatorView.h>
32#include <Window.h>
33
34
35#include <math.h>
36#include <stdio.h>
37
38
39#undef B_TRANSLATION_CONTEXT"Tools"
40#define B_TRANSLATION_CONTEXT"Tools" "Tools"
41
42
43using ArtPaint::Interface::NumberSliderControl;
44
45
46StraightLineTool::StraightLineTool()
47 : DrawingTool(B_TRANSLATE("Straight line tool")BLocaleRoster::Default()->GetCatalog()->GetString(("Straight line tool"
), "Tools")
,
48 STRAIGHT_LINE_TOOL)
49{
50 fOptions = SIZE_OPTION | ANTI_ALIASING_LEVEL_OPTION | MODE_OPTION;
51 fOptionsCount = 3;
52
53 SetOption(SIZE_OPTION, 1);
54 SetOption(MODE_OPTION, B_CONTROL_ON);
55 SetOption(ANTI_ALIASING_LEVEL_OPTION, B_CONTROL_OFF);
56}
57
58
59StraightLineTool::~StraightLineTool()
60{
61}
62
63
64ToolScript*
65StraightLineTool::UseTool(ImageView* view, uint32 buttons, BPoint point,
66 BPoint view_point)
67{
68 // In this function we calculate the line as a polygon. We make the polygon
69 // by first making a horizontal rectangle of appropriate size and the
70 // rotating around the starting-point by proper angle.
71
72 // Wait for the last_updated_region to become empty
73 while (LastUpdatedRect().IsValid())
1
Loop condition is false. Execution continues on line 76
74 snooze(50000);
75
76 BWindow *window = view->Window();
77 drawing_mode old_mode;
78 BBitmap *bitmap = view->ReturnImage()->ReturnActiveBitmap();
79// BView *bitmap_view = view->getBufferView();
80
81 Selection *selection = view->GetSelection();
82
83 if (window != NULL__null) {
2
Assuming 'window' is not equal to NULL
3
Taking true branch
84 ToolScript* the_script = new ToolScript(Type(), fToolSettings,
85 ((PaintApplication*)be_app)->Color(true));
86
87 BitmapDrawer *drawer = new BitmapDrawer(bitmap);
88
89 BPoint original_point,original_view_point,prev_view_point;
90 BRect bitmap_rect,old_rect,new_rect;
91 HSPolygon *view_polygon = NULL__null;
4
'view_polygon' initialized to a null pointer value
92 BPoint point_list[4];
93
94 window->Lock();
95 old_mode = view->DrawingMode();
96 view->SetDrawingMode(B_OP_INVERT);
97 window->Unlock();
98 original_point = point;
99 rgb_color c = ((PaintApplication*)be_app)->Color(true);
100
101 prev_view_point = original_view_point = view_point;
102 bitmap_rect = BRect(point.x, point.y -
103 floor(((float)GetCurrentValue(SIZE_OPTION) - 1.0) / 2.0), point.x,
104 point.y + ceil(((float)GetCurrentValue(SIZE_OPTION) - 1.0) / 2.0));
105 old_rect = new_rect = view->convertBitmapRectToView(bitmap_rect);
106 point_list[0] = new_rect.LeftTop();
107 point_list[1] = new_rect.RightTop();
108 point_list[2] = new_rect.RightBottom();
109 point_list[3] = new_rect.LeftBottom();
110
111 window->Lock();
112 if ((GetCurrentValue(SIZE_OPTION) > 2) && (fToolSettings.mode == B_CONTROL_OFF)) {
5
Assuming the condition is false
113 view_polygon = new HSPolygon(point_list,4);
114 BPolygon *bpoly = view_polygon->GetBPolygon();
115 view->StrokePolygon(bpoly);
116 delete bpoly;
117 }
118 else
119 view->StrokeLine(original_view_point,view_point);
120 window->Unlock();
121
122 float angle = 0;
123 while (buttons) {
6
Loop condition is true. Entering loop body
124 window->Lock();
125 view->getCoords(&point,&buttons,&view_point);
126 if (modifiers() & B_LEFT_SHIFT_KEY) {
7
Assuming the condition is false
8
Taking false branch
127 // Make the new point be so that the angle is a multiple of 45°.
128 float x_diff,y_diff;
129 x_diff = fabs(original_point.x-point.x);
130 y_diff = fabs(original_point.y-point.y);
131
132 if (x_diff < y_diff) {
133 if (x_diff < y_diff/2)
134 x_diff = 0;
135 else
136 x_diff = y_diff;
137 }
138 else {
139 if (y_diff < x_diff/2)
140 y_diff = 0;
141 else
142 y_diff = x_diff;
143 }
144
145 float signed_x_diff = (point.x-original_point.x);
146 float signed_y_diff = (point.y-original_point.y);
147
148 if (signed_x_diff != 0)
149 point.x = original_point.x + x_diff * signed_x_diff/fabs(signed_x_diff);
150
151 if (signed_y_diff != 0)
152 point.y = original_point.y + y_diff * signed_y_diff/fabs(signed_y_diff);
153
154 x_diff = fabs(original_view_point.x-view_point.x);
155 y_diff = fabs(original_view_point.y-view_point.y);
156
157 if (x_diff < y_diff) {
158 if (x_diff < y_diff/2)
159 x_diff = 0;
160 else
161 x_diff = y_diff;
162 }
163 else {
164 if (y_diff < x_diff/2)
165 y_diff = 0;
166 else
167 y_diff = x_diff;
168 }
169
170
171 signed_x_diff = (view_point.x-original_view_point.x);
172 signed_y_diff = (view_point.y-original_view_point.y);
173 if (signed_x_diff != 0) {
174 view_point.x = original_view_point.x +
175 x_diff * signed_x_diff / fabs(signed_x_diff);
176 }
177
178 if (signed_y_diff != 0) {
179 view_point.y = original_view_point.y +
180 y_diff * signed_y_diff / fabs(signed_y_diff);
181 }
182 }
183
184 bitmap_rect = BRect(original_point.x,
185 original_point.y - floor(((float)GetCurrentValue(SIZE_OPTION) - 1.0) / 2.0),
186 original_point.x + sqrt(pow(original_point.x - point.x, 2) +
187 pow(original_point.y - point.y, 2)), original_point.y +
188 ceil(((float)GetCurrentValue(SIZE_OPTION) - 1.0) / 2.0));
189
190 new_rect = view->convertBitmapRectToView(bitmap_rect);
191 if (old_rect != new_rect) {
9
Assuming the condition is true
10
Taking true branch
192 if ((GetCurrentValue(SIZE_OPTION) > 2) && (fToolSettings.mode == B_CONTROL_OFF)) {
11
Assuming the condition is true
12
Assuming field 'mode' is equal to B_CONTROL_OFF
13
Taking true branch
193 BRect bbox = view_polygon->BoundingBox();
14
Called C++ object pointer is null
194 view->Draw(bbox);
195 point_list[0] = new_rect.LeftTop();
196 point_list[1] = new_rect.RightTop();
197 point_list[2] = new_rect.RightBottom();
198 point_list[3] = new_rect.LeftBottom();
199 view_polygon = new HSPolygon(point_list,4);
200 angle = atan2((view_point.y-original_view_point.y),
201 (view_point.x - original_view_point.x)) * 180 / M_PI3.14159265358979323846;
202 view_polygon->Rotate(original_view_point,angle);
203 BPolygon *bpoly = view_polygon->GetBPolygon();
204 view->StrokePolygon(bpoly);
205 delete bpoly;
206 }
207 else {
208 float left = min_c(original_view_point.x, prev_view_point.x)((original_view_point.x)>(prev_view_point.x)?(prev_view_point
.x):(original_view_point.x))
;
209 float top = min_c(original_view_point.y, prev_view_point.y)((original_view_point.y)>(prev_view_point.y)?(prev_view_point
.y):(original_view_point.y))
;
210 float right = max_c(original_view_point.x, prev_view_point.x)((original_view_point.x)>(prev_view_point.x)?(original_view_point
.x):(prev_view_point.x))
;
211 float bottom = max_c(original_view_point.y, prev_view_point.y)((original_view_point.y)>(prev_view_point.y)?(original_view_point
.y):(prev_view_point.y))
;
212 BRect bbox(left, top, right, bottom);
213 view->Draw(bbox);
214 view->StrokeLine(original_view_point,view_point);
215 angle = atan2((view_point.y-original_view_point.y),
216 (view_point.x - original_view_point.x)) * 180 / M_PI3.14159265358979323846;
217 prev_view_point = view_point;
218 }
219 old_rect = new_rect;
220 }
221 window->Unlock();
222 snooze(20 * 1000);
223 }
224 int32 size = GetCurrentValue(SIZE_OPTION);
225 bool draw_line = true;
226 new_rect = old_rect;
227 if (fToolSettings.mode == B_CONTROL_ON) { // Adjust the width of the line.
228 bool continue_adjusting_width = true;
229 BPoint p1 = original_point;
230 BPoint width_point;
231 view_polygon = new HSPolygon(NULL__null,0);
232 BRect orig_rect = bitmap_rect;
233 orig_rect.bottom = orig_rect.top = original_point.y;
234
235 size = 0;
236
237 while (continue_adjusting_width) {
238 if (is_clicks_data_valid) {
239 continue_adjusting_width = false;
240 is_clicks_data_valid = false;
241 }
242 else if (is_keys_data_valid) {
243 if (last_key_event_bytes[0] == B_ESCAPE) {
244 continue_adjusting_width = false;
245 draw_line = false;
246 }
247 is_keys_data_valid = false;
248 }
249 else {
250 if (view->LockLooper()) {
251 new_rect = orig_rect;
252 new_rect.bottom += size/2;
253 new_rect.top -= size/2;
254 new_rect = view->convertBitmapRectToView(new_rect);
255 if (new_rect != old_rect) {
256 if (size > 0) {
257 BRect bbox = view_polygon->BoundingBox();
258 view->Draw(bbox);
259 point_list[0] = new_rect.LeftTop();
260 point_list[1] = new_rect.RightTop();
261 point_list[2] = new_rect.RightBottom();
262 point_list[3] = new_rect.LeftBottom();
263 view_polygon = new HSPolygon(point_list,4);
264 view_polygon->Rotate(original_view_point,angle);
265 BPolygon* bpoly = view_polygon->GetBPolygon();
266 view->StrokePolygon(bpoly);
267 delete bpoly;
268 }
269 old_rect = new_rect;
270 }
271 view->getCoords(&width_point,&buttons);
272 view->UnlockLooper();
273 width_point = width_point-p1;
274 BPoint spare = width_point;
275 width_point.x = cos(-angle / 180 * M_PI3.14159265358979323846) * spare.x -
276 sin(-angle / 180 * M_PI3.14159265358979323846) * spare.y;
277 width_point.y = sin(-angle / 180 * M_PI3.14159265358979323846) * spare.x +
278 cos(-angle / 180 * M_PI3.14159265358979323846) * spare.y;
279 size = (int32)(2 * fabs(width_point.y));
280 }
281 snooze(20 * 1000);
282 }
283 }
284 }
285 delete view_polygon;
286
287 bool anti_alias = true;
288 if (GetCurrentValue(ANTI_ALIASING_LEVEL_OPTION) == B_CONTROL_OFF)
289 anti_alias = false;
290
291 if (size > 1)
292 drawer->DrawLine(original_point,point,RGBColorToBGRA(c),size,anti_alias,selection);
293 else
294 drawer->DrawHairLine(original_point,point,RGBColorToBGRA(c),anti_alias,selection);
295
296 BRect updated_rect = MakeRectFromPoints(original_point, point);
297
298 // This extension might actually be too little.
299 updated_rect.left -= size/2;
300 updated_rect.top -= size/2;
301 updated_rect.right += size/2;
302 updated_rect.bottom += size/2;
303
304 SetLastUpdatedRect(updated_rect);
305 window->Lock();
306 view->SetDrawingMode(old_mode);
307 view->UpdateImage(updated_rect);
308 view->Sync();
309 window->Unlock();
310
311 delete drawer;
312
313 the_script->AddPoint(original_point);
314 the_script->AddPoint(point);
315 return the_script;
316 }
317
318 return NULL__null;
319}
320
321
322int32
323StraightLineTool::UseToolWithScript(ToolScript*,BBitmap*)
324{
325 return B_OK((int)0);
326}
327
328
329BView*
330StraightLineTool::ConfigView()
331{
332 return new StraightLineToolConfigView(this);
333}
334
335
336const void*
337StraightLineTool::ToolCursor() const
338{
339 return HS_LINE_CURSOR;
340}
341
342
343const char*
344StraightLineTool::HelpString(bool isInUse) const
345{
346 return (isInUse
347 ? B_TRANSLATE("Drawing a straight line.")BLocaleRoster::Default()->GetCatalog()->GetString(("Drawing a straight line."
), "Tools")
348 : B_TRANSLATE("Click to draw a straight line.")BLocaleRoster::Default()->GetCatalog()->GetString(("Click to draw a straight line."
), "Tools")
);
349}
350
351
352// #pragma mark -- StraightLineToolConfigView
353
354
355StraightLineToolConfigView::StraightLineToolConfigView(DrawingTool* tool)
356 : DrawingToolConfigView(tool)
357{
358 if (BLayout* layout = GetLayout()) {
359 BMessage* message = new BMessage(OPTION_CHANGED);
360 message->AddInt32("option", SIZE_OPTION);
361 message->AddInt32("value", tool->GetCurrentValue(SIZE_OPTION));
362
363 fLineSize = new NumberSliderControl(
364 B_TRANSLATE("Width:")BLocaleRoster::Default()->GetCatalog()->GetString(("Width:"
), "Tools")
,
365 "1", message, 1, 100, false);
366
367 message = new BMessage(OPTION_CHANGED);
368 message->AddInt32("option", ANTI_ALIASING_LEVEL_OPTION);
369 message->AddInt32("value", 0x00000000);
370
371 fAntiAliasing =
372 new BCheckBox(B_TRANSLATE("Enable antialiasing")BLocaleRoster::Default()->GetCatalog()->GetString(("Enable antialiasing"
), "Tools")
,
373 message);
374 if (tool->GetCurrentValue(ANTI_ALIASING_LEVEL_OPTION) != B_CONTROL_OFF)
375 fAntiAliasing->SetValue(B_CONTROL_ON);
376
377 message = new BMessage(OPTION_CHANGED);
378 message->AddInt32("option", MODE_OPTION);
379 message->AddInt32("value", 0x00000000);
380
381 fAdjustableWidth =
382 new BCheckBox(B_TRANSLATE("Adjustable width")BLocaleRoster::Default()->GetCatalog()->GetString(("Adjustable width"
), "Tools")
,
383 message);
384 if (tool->GetCurrentValue(MODE_OPTION) != B_CONTROL_OFF)
385 fAdjustableWidth->SetValue(B_CONTROL_ON);
386
387 BGridLayout* lineSizeLayout = LayoutSliderGrid(fLineSize);
388
389 layout->AddView(BGroupLayoutBuilder(B_VERTICAL, kWidgetSpacing)
390 .Add(lineSizeLayout)
391 .AddStrut(kWidgetSpacing)
392 .Add(SeparatorView(B_TRANSLATE("Options")BLocaleRoster::Default()->GetCatalog()->GetString(("Options"
), "Tools")
))
393 .AddGroup(B_VERTICAL, kWidgetSpacing)
394 .Add(fAdjustableWidth)
395 .Add(fAntiAliasing)
396 .SetInsets(kWidgetInset, 0.0, 0.0, 0.0)
397 .End()
398 .TopView()
399 );
400 }
401}
402
403
404void
405StraightLineToolConfigView::AttachedToWindow()
406{
407 DrawingToolConfigView::AttachedToWindow();
408
409 fLineSize->SetTarget(this);
410 fAntiAliasing->SetTarget(this);
411 fAdjustableWidth->SetTarget(this);
412}