Bug Summary

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