Bug Summary

File:home/HaikuArchives/ArtPaint/artpaint/tools/BrushTool.cpp
Warning:line 311, column 10
Value stored to 'target_bits' during its initialization is never read

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 BrushTool.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-07-02-122529-1240-1 -x c++ artpaint/tools/BrushTool.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 "BrushTool.h"
14
15#include "BitmapUtilities.h"
16#include "Brush.h"
17#include "BrushEditor.h"
18#include "CoordinateReader.h"
19#include "CoordinateQueue.h"
20#include "Cursors.h"
21#include "Image.h"
22#include "ImageUpdater.h"
23#include "ImageView.h"
24#include "PaintApplication.h"
25#include "PixelOperations.h"
26#include "Selection.h"
27#include "ToolScript.h"
28#include "UtilityClasses.h"
29
30
31#include <Catalog.h>
32#include <File.h>
33#include <Layout.h>
34#include <Window.h>
35
36
37#undef B_TRANSLATION_CONTEXT"Tools"
38#define B_TRANSLATION_CONTEXT"Tools" "Tools"
39
40
41BrushTool::BrushTool()
42 : DrawingTool(B_TRANSLATE("Brush tool")BLocaleRoster::Default()->GetCatalog()->GetString(("Brush tool"
), "Tools")
, BRUSH_TOOL)
43{
44 // Options will also have some brush-data options.
45 fOptions = 0;
46 fOptionsCount = 0;
47
48 brush_info info;
49 info.shape = HS_ELLIPTICAL_BRUSH;
50 info.width = 30;
51 info.height = 30;
52 info.angle = 0;
53 info.hardness = 2;
54
55 brush = new Brush(info);
56}
57
58
59BrushTool::~BrushTool()
60{
61 delete brush;
62}
63
64
65ToolScript*
66BrushTool::UseTool(ImageView *view, uint32 buttons, BPoint point, BPoint viewPoint)
67{
68 B_UNUSED(buttons)(void)buttons;
69 B_UNUSED(viewPoint)(void)viewPoint;
70
71 // Wait for the last_updated_region to become empty
72 while (LastUpdatedRect().IsValid())
73 snooze(50000);
74
75 CoordinateReader* coordinate_reader =
76 new (std::nothrow) CoordinateReader(view, LINEAR_INTERPOLATION, false);
77 if (coordinate_reader == NULL__null)
78 return NULL__null;
79
80 ToolScript* the_script = new (std::nothrow) ToolScript(Type(),
81 fToolSettings, ((PaintApplication*)be_app)->Color(true));
82 if (the_script == NULL__null) {
83 delete coordinate_reader;
84 return NULL__null;
85 }
86
87 selection = view->GetSelection();
88
89 BBitmap* buffer = view->ReturnImage()->ReturnActiveBitmap();
90 BBitmap* srcBuffer = new (std::nothrow) BBitmap(buffer);
91 if (srcBuffer == NULL__null) {
92 delete coordinate_reader;
93 delete the_script;
94 return NULL__null;
95 }
96
97 bits = (uint32*)buffer->Bits();
98 bpr = buffer->BytesPerRow()/4;
99 BRect bitmap_bounds = buffer->Bounds();
100
101 left_bound = (int32)bitmap_bounds.left;
102 right_bound = (int32)bitmap_bounds.right;
103 top_bound = (int32)bitmap_bounds.top;
104 bottom_bound = (int32)bitmap_bounds.bottom;
105
106 BBitmap* tmpBuffer = new (std::nothrow) BBitmap(bitmap_bounds,
107 buffer->ColorSpace());
108 if (tmpBuffer == NULL__null) {
109 delete coordinate_reader;
110 delete the_script;
111 delete srcBuffer;
112 return NULL__null;
113 }
114
115 float brush_width_per_2 = floor(brush->Width()/2);
116 float brush_height_per_2 = floor(brush->Height()/2);
117
118 BPoint prev_point;
119
120 union color_conversion new_color;
121
122 new_color.word =
123 RGBColorToBGRA(((PaintApplication*)be_app)->Color(true));
124
125 union color_conversion clear_color;
126 clear_color.word = new_color.word;
127 clear_color.bytes[3] = 0x01;
128
129 BitmapUtilities::ClearBitmap(tmpBuffer, clear_color.word);
130
131 prev_point = last_point = point;
132 BRect updated_rect;
133
134 the_script->AddPoint(point);
135
136 if (coordinate_reader->GetPoint(point) == B_OK((int)0)) {
137 draw_brush(tmpBuffer, BPoint(point.x - brush_width_per_2,
138 point.y - brush_height_per_2), 0, 0, new_color.word);
139 }
140
141 updated_rect = BRect(point.x - brush_width_per_2,
142 point.y - brush_height_per_2, point.x + brush_width_per_2,
143 point.y + brush_height_per_2);
144 SetLastUpdatedRect(updated_rect);
145 buffer->Lock();
146 BitmapUtilities::CompositeBitmapOnSource(buffer, srcBuffer,
147 tmpBuffer, updated_rect);
148 buffer->Unlock();
149 prev_point = point;
150
151 ImageUpdater* imageUpdater = new ImageUpdater(view, 20000);
152 imageUpdater->AddRect(updated_rect);
153
154 while (coordinate_reader->GetPoint(point) == B_OK((int)0)) {
155 draw_brush(tmpBuffer, BPoint(point.x - brush_width_per_2,
156 point.y - brush_height_per_2), int32(point.x - prev_point.x),
157 int32(point.y - prev_point.y), new_color.word);
158 updated_rect = BRect(point.x - brush_width_per_2,
159 point.y - brush_height_per_2, point.x + brush_width_per_2,
160 point.y + brush_height_per_2);
161 imageUpdater->AddRect(updated_rect);
162 SetLastUpdatedRect(updated_rect | LastUpdatedRect());
163 buffer->Lock();
164 BitmapUtilities::CompositeBitmapOnSource(buffer, srcBuffer,
165 tmpBuffer, updated_rect);
166 buffer->Unlock();
167 prev_point = point;
168 }
169
170 imageUpdater->ForceUpdate();
171
172 delete imageUpdater;
173 delete coordinate_reader;
174
175// test_brush(point,new_color);
176// if (view->LockLooper() == true) {
177// view->UpdateImage(view->Bounds());
178// view->Invalidate();
179// view->UnlockLooper();
180// }
181
182 delete srcBuffer;
183 delete tmpBuffer;
184
185 return the_script;
186}
187
188
189int32
190BrushTool::UseToolWithScript(ToolScript*, BBitmap*)
191{
192 return B_OK((int)0);
193}
194
195
196BView*
197BrushTool::ConfigView()
198{
199 return new BrushToolConfigView(this);
200}
201
202
203const void*
204BrushTool::ToolCursor() const
205{
206 return HS_BRUSH_CURSOR;
207}
208
209
210const char*
211BrushTool::HelpString(bool isInUse) const
212{
213 return (isInUse
214 ? B_TRANSLATE("Painting with a brush.")BLocaleRoster::Default()->GetCatalog()->GetString(("Painting with a brush."
), "Tools")
215 : B_TRANSLATE("Click to paint with a brush.")BLocaleRoster::Default()->GetCatalog()->GetString(("Click to paint with a brush."
), "Tools")
);
216}
217
218
219BRect
220BrushTool::draw_line(BBitmap* buffer, BPoint start,BPoint end,uint32 color)
221{
222 int32 brush_width_per_2 = (int32)floor(brush->Width()/2);
223 int32 brush_height_per_2 = (int32)floor(brush->Height()/2);
224 BRect a_rect = MakeRectFromPoints(start, end);
225 a_rect.InsetBy(-brush_width_per_2-1,-brush_height_per_2-1);
226 // first check whether the line is longer in x direction than y
227 bool increase_x = fabs(start.x - end.x) >= fabs(start.y - end.y);
228 // check which direction the line is going
229 float sign_x;
230 float sign_y;
231 int32 number_of_points;
232 if ((end.x-start.x) != 0) {
233 sign_x = (end.x-start.x)/fabs(start.x - end.x);
234 }
235 else {
236 sign_x = 0;
237 }
238 if ((end.y-start.y) != 0) {
239 sign_y = (end.y-start.y)/fabs(start.y - end.y);
240 }
241 else {
242 sign_y = 0;
243 }
244 int32 dx,dy;
245 int32 last_x,last_y;
246 int32 new_x,new_y;
247
248 if (increase_x) {
249 float y_add = ((float)fabs(start.y - end.y)) / ((float)fabs(start.x - end.x));
250 number_of_points = (int32)fabs(start.x-end.x);
251 for (int32 i=0;i<number_of_points;i++) {
252 last_point = start;
253 start.x += sign_x;
254 start.y += sign_y * y_add;
255 new_x = (int32)round(start.x);
256 new_y = (int32)round(start.y);
257 last_x = (int32)round(last_point.x);
258 last_y = (int32)round(last_point.y);
259
260 dx = new_x - last_x;
261 dy = new_y - last_y;
262 draw_brush(buffer, BPoint(new_x - brush_width_per_2, new_y -
263 brush_height_per_2), dx, dy, color);
264
265// view->Window()->Lock();
266// view->Invalidate();
267// view->Window()->Unlock();
268// snooze(50 * 1000);
269 }
270 }
271
272 else {
273 float x_add = ((float)fabs(start.x - end.x)) / ((float)fabs(start.y - end.y));
274 number_of_points = (int32)fabs(start.y-end.y);
275 for (int32 i=0;i<number_of_points;i++) {
276 last_point = start;
277 start.y += sign_y;
278 start.x += sign_x * x_add;
279 new_x = (int32)round(start.x);
280 new_y = (int32)round(start.y);
281 last_x = (int32)round(last_point.x);
282 last_y = (int32)round(last_point.y);
283
284 dx = new_x - last_x;
285 dy = new_y - last_y;
286 draw_brush(buffer, BPoint(new_x-brush_width_per_2,new_y-brush_height_per_2),dx,dy,color);
287
288// view->Window()->Lock();
289// view->Invalidate();
290// view->Window()->Unlock();
291// snooze(50 * 1000);
292 }
293 }
294 return a_rect;
295}
296
297
298void
299BrushTool::draw_brush(BBitmap* buffer, BPoint point,
300 int32 dx, int32 dy, uint32 c)
301{
302 span* spans;
303 int32 px = (int32)point.x;
304 int32 py = (int32)point.y;
305 uint32** brush_matrix = brush->GetData(&spans, dx, dy);
306
307 if (brush_matrix == NULL__null)
308 return;
309
310 bits = (uint32*)buffer->Bits();
311 uint32* target_bits = bits;
Value stored to 'target_bits' during its initialization is never read
312 while ((spans != NULL__null) && (spans->row + py <= bottom_bound)) {
313 int32 left = max_c(px + spans->span_start, left_bound)((px + spans->span_start)>(left_bound)?(px + spans->
span_start):(left_bound))
;
314 int32 right = min_c(px + spans->span_end, right_bound)((px + spans->span_end)>(right_bound)?(right_bound):(px
+ spans->span_end))
;
315 int32 y = spans->row;
316 if (y + py >= top_bound) {
317 // This works even if there are many spans in one row.
318 target_bits = bits + (y + py) * bpr + left;
319 for (int32 x = left; x <= right; ++x) {
320 if (selection->IsEmpty() || selection->ContainsPoint(x, y + py)) {
321
322 *target_bits = mix_2_pixels_fixed(c, *target_bits,
323 brush_matrix[y][x-px]);
324 }
325 target_bits++;
326 }
327 }
328 spans = spans->next;
329 }
330}
331
332
333status_t
334BrushTool::readSettings(BFile &file, bool isLittleEndian)
335{
336 int32 length;
337 if (file.Read(&length,sizeof(int32)) != sizeof(int32))
338 return B_ERROR(-1);
339
340 if (isLittleEndian)
341 length = B_LENDIAN_TO_HOST_INT32(length)(uint32)(length);
342 else
343 length = B_BENDIAN_TO_HOST_INT32(length)(uint32)__builtin_bswap32(length);
344
345 int32 version;
346 if (file.Read(&version,sizeof(int32)) != sizeof(int32))
347 return B_ERROR(-1);
348
349 if (isLittleEndian)
350 version = B_LENDIAN_TO_HOST_INT32(version)(uint32)(version);
351 else
352 version = B_BENDIAN_TO_HOST_INT32(version)(uint32)__builtin_bswap32(version);
353
354 if (version != TOOL_SETTINGS_STRUCT_VERSION0x00000001) {
355 file.Seek(length - sizeof(int32), SEEK_CUR1);
356 return B_ERROR(-1);
357 }
358
359 // Here we should take the endianness into account.
360 brush_info info;
361 if (file.Read(&info, sizeof(struct brush_info)) != sizeof(struct brush_info))
362 return B_ERROR(-1);
363
364 delete brush;
365 brush = new Brush(info);
366
367 return B_OK((int)0);
368}
369
370
371status_t
372BrushTool::writeSettings(BFile &file)
373{
374 int32 type = Type();
375 if (file.Write(&type, sizeof(int32)) != sizeof(int32))
376 return B_ERROR(-1);
377
378 int32 settings_size = sizeof(struct brush_info) + sizeof(int32);
379 if (file.Write(&settings_size,sizeof(int32)) != sizeof(int32))
380 return B_ERROR(-1);
381
382 int32 settings_version = TOOL_SETTINGS_STRUCT_VERSION0x00000001;
383 if (file.Write(&settings_version,sizeof(int32)) != sizeof(int32))
384 return B_ERROR(-1);
385
386 brush_info info;
387 info = brush->GetInfo();
388 if (file.Write(&info,sizeof(struct brush_info)) != sizeof(struct brush_info))
389 return B_ERROR(-1);
390
391 return B_OK((int)0);
392}
393
394
395// #pragma mark -- BrushToolConfigView
396
397
398BrushToolConfigView::BrushToolConfigView(DrawingTool* tool)
399 : DrawingToolConfigView(tool)
400{
401 if (BLayout* layout = GetLayout()) {
402 BrushTool* brushTool = dynamic_cast<BrushTool*> (tool);
403 layout->AddView(BrushEditor::CreateBrushEditor(brushTool->GetBrush()));
404 }
405}