Icon-O-Matic: Fix multiple point handling

Fixes #16760

The problem comes from trying to cast a void* array to an int32 array.
However, sizeof(void*) is not always equal to sizeof(int32).

Change-Id: I12b7f71621f150edb732b5e0a7d84bf7ced5444a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/6871
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Zardshard
2023-08-25 18:55:40 +00:00
committed by waddlesplash
parent b22fab9510
commit 0a5625377a
+112 -123
View File
@@ -1,12 +1,18 @@
/* /*
* Copyright 2006-2009, Stephan Aßmus <[email protected]>. * Copyright 2006-2009, Stephan Aßmus <[email protected]>.
* Copyright 2023, Haiku, Inc.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*
* Authors:
* Zardshard
*/ */
#include "PathManipulator.h" #include "PathManipulator.h"
#include <algorithm>
#include <float.h> #include <float.h>
#include <stdio.h> #include <stdio.h>
#include <vector>
#include <Catalog.h> #include <Catalog.h>
#include <Cursor.h> #include <Cursor.h>
@@ -126,84 +132,68 @@ string_for_mode(uint32 mode)
return "<unknown mode>"; return "<unknown mode>";
} }
class PathManipulator::Selection : protected BList // NOTE: this class extends std::vector<int32> since neither BList or
// BObjectList would suffice. The backing array of BList and BObjectList is a
// void* array. The Items function should return an int32 array. This is a
// problem since sizeof(void*) is not necessarily equal to sizeof(int32).
class PathManipulator::Selection : protected std::vector<int32>
{ {
public: public:
inline Selection(int32 count = 20) inline Selection(int32 count = 20)
: BList(count) {} : _inherited() { reserve(count); }
inline ~Selection() {} inline ~Selection() {}
inline void Add(int32 value) inline void Add(int32 value)
{ {
if (value >= 0) { if (value >= 0) {
// keep the list sorted // keep the list sorted
int32 count = CountItems(); insert(std::upper_bound(begin(), end(), value), value);
int32 index = 0;
for (; index < count; index++) {
if (IndexAt(index) > value) {
break;
}
}
BList::AddItem((void*)(long)value, index);
}
} }
}
inline bool Remove(int32 value) inline bool Remove(int32 value)
{ return BList::RemoveItem((void*)(long)value); } {
if (!Contains(value))
return false;
erase(std::lower_bound(begin(), end(), value));
return true;
}
inline bool Contains(int32 value) const inline bool Contains(int32 value) const
{ return BList::HasItem((void*)(long)value); } { return std::binary_search(begin(), end(), value); }
inline bool IsEmpty() const inline bool IsEmpty() const
{ return BList::IsEmpty(); } { return size() == 0; }
inline int32 IndexAt(int32 index) const inline int32 IndexAt(int32 index) const
{ return (int32)(long)BList::ItemAt(index); } { return at(index); }
inline void MakeEmpty() inline void MakeEmpty()
{ BList::MakeEmpty(); } { clear(); }
inline int32* Items() const inline const int32* Items() const
{ return (int32*)BList::Items(); } { return &(*this)[0]; }
inline const int32 CountItems() const inline const int32 CountItems() const
{ return BList::CountItems(); } { return size(); }
inline Selection& operator =(const Selection& other) inline Selection& operator =(const Selection& other)
{ {
MakeEmpty(); _inherited::operator=(other);
int32 count = other.CountItems(); return *this;
int32* items = other.Items(); }
for (int32 i = 0; i < count; i++) {
Add(items[i]);
}
return *this;
}
inline bool operator ==(const Selection& other) inline bool operator ==(const Selection& other)
{ { return (_inherited)*this == (_inherited)other; }
if (other.CountItems() == CountItems()) {
int32* items = Items();
int32* otherItems = other.Items();
for (int32 i = 0; i < CountItems(); i++) {
if (items[i] != otherItems[i])
return false;
items++;
otherItems++;
}
return true;
} else
return false;
}
inline bool operator !=(const Selection& other) inline bool operator !=(const Selection& other)
{ { return (_inherited)*this != (_inherited)other; }
return !(*this == other);
} private:
typedef std::vector<int32> _inherited;
}; };
// constructor
PathManipulator::PathManipulator(VectorPath* path) PathManipulator::PathManipulator(VectorPath* path)
: Manipulator(NULL), : Manipulator(NULL),
fCanvasView(NULL), fCanvasView(NULL),
@@ -240,7 +230,7 @@ PathManipulator::PathManipulator(VectorPath* path)
fPath->AddObserver(this); fPath->AddObserver(this);
} }
// destructor
PathManipulator::~PathManipulator() PathManipulator::~PathManipulator()
{ {
delete fChangePointCommand; delete fChangePointCommand;
@@ -261,6 +251,7 @@ PathManipulator::~PathManipulator()
// #pragma mark - // #pragma mark -
class StrokePathIterator : public VectorPath::Iterator { class StrokePathIterator : public VectorPath::Iterator {
public: public:
StrokePathIterator(CanvasView* canvasView, StrokePathIterator(CanvasView* canvasView,
@@ -292,7 +283,7 @@ class StrokePathIterator : public VectorPath::Iterator {
else else
fDrawingView->SetHighColor(0, 0, 0, 255); fDrawingView->SetHighColor(0, 0, 0, 255);
fBlack = !fBlack; fBlack = !fBlack;
fDrawingView->StrokeLine(point); fDrawingView->StrokeLine(point);
} else { } else {
fDrawingView->MovePenTo(point); fDrawingView->MovePenTo(point);
@@ -307,7 +298,7 @@ class StrokePathIterator : public VectorPath::Iterator {
bool fSkip; bool fSkip;
}; };
// Draw
void void
PathManipulator::Draw(BView* into, BRect updateRect) PathManipulator::Draw(BView* into, BRect updateRect)
{ {
@@ -405,9 +396,10 @@ PathManipulator::Draw(BView* into, BRect updateRect)
} }
} }
// #pragma mark - // #pragma mark -
// MouseDown
bool bool
PathManipulator::MouseDown(BPoint where) PathManipulator::MouseDown(BPoint where)
{ {
@@ -556,7 +548,7 @@ PathManipulator::MouseDown(BPoint where)
return true; return true;
} }
// MouseMoved
void void
PathManipulator::MouseMoved(BPoint where) PathManipulator::MouseMoved(BPoint where)
{ {
@@ -615,7 +607,7 @@ PathManipulator::MouseMoved(BPoint where)
// drag out control point // drag out control point
fPath->SetPointOut(fCurrentPathPoint, canvasWhere); fPath->SetPointOut(fCurrentPathPoint, canvasWhere);
break; break;
case SELECT_POINTS: { case SELECT_POINTS: {
// change the selection // change the selection
BRect r; BRect r;
@@ -636,7 +628,7 @@ PathManipulator::MouseMoved(BPoint where)
} }
} }
// MouseUp
Command* Command*
PathManipulator::MouseUp() PathManipulator::MouseUp()
{ {
@@ -715,7 +707,7 @@ PathManipulator::MouseUp()
return command; return command;
} }
// MouseOver
bool bool
PathManipulator::MouseOver(BPoint where) PathManipulator::MouseOver(BPoint where)
{ {
@@ -746,14 +738,14 @@ PathManipulator::MouseOver(BPoint where)
return true; return true;
} }
// DoubleClicked
bool bool
PathManipulator::DoubleClicked(BPoint where) PathManipulator::DoubleClicked(BPoint where)
{ {
return false; return false;
} }
// ShowContextMenu
bool bool
PathManipulator::ShowContextMenu(BPoint where) PathManipulator::ShowContextMenu(BPoint where)
{ {
@@ -777,7 +769,7 @@ PathManipulator::ShowContextMenu(BPoint where)
message = new BMessage(B_SELECT_ALL); message = new BMessage(B_SELECT_ALL);
item = new BMenuItem(B_TRANSLATE("Select all"), message, 'A'); item = new BMenuItem(B_TRANSLATE("Select all"), message, 'A');
menu->AddItem(item); menu->AddItem(item);
menu->AddSeparatorItem(); menu->AddSeparatorItem();
} }
@@ -814,9 +806,10 @@ PathManipulator::ShowContextMenu(BPoint where)
return true; return true;
} }
// #pragma mark - // #pragma mark -
// Bounds
BRect BRect
PathManipulator::Bounds() PathManipulator::Bounds()
{ {
@@ -825,16 +818,17 @@ PathManipulator::Bounds()
return r; return r;
} }
// TrackingBounds
BRect BRect
PathManipulator::TrackingBounds(BView* withinView) PathManipulator::TrackingBounds(BView* withinView)
{ {
return withinView->Bounds(); return withinView->Bounds();
} }
// #pragma mark - // #pragma mark -
// MessageReceived
bool bool
PathManipulator::MessageReceived(BMessage* message, Command** _command) PathManipulator::MessageReceived(BMessage* message, Command** _command)
{ {
@@ -858,22 +852,13 @@ PathManipulator::MessageReceived(BMessage* message, Command** _command)
fSelection->CountItems()); fSelection->CountItems());
break; break;
case B_SELECT_ALL: { case B_SELECT_ALL: {
*fOldSelection = *fSelection;
fSelection->MakeEmpty();
int32 count = fPath->CountPoints(); int32 count = fPath->CountPoints();
int32 indices[count];
for (int32 i = 0; i < count; i++) for (int32 i = 0; i < count; i++)
fSelection->Add(i); indices[i] = i;
if (*fOldSelection != *fSelection) {
// *_command = new SelectPointsCommand(this, fPath, _Select(indices, count);
// fOldSelection->Items(),
// fOldSelection->CountItems(),
// fSelection->Items(),
// fSelection->CountItems()));
count = fSelection->CountItems();
int32 indices[count];
memcpy(indices, fSelection->Items(), count * sizeof(int32));
_Select(indices, count);
}
break; break;
} }
default: default:
@@ -884,7 +869,6 @@ PathManipulator::MessageReceived(BMessage* message, Command** _command)
} }
// ModifiersChanged
void void
PathManipulator::ModifiersChanged(uint32 modifiers) PathManipulator::ModifiersChanged(uint32 modifiers)
{ {
@@ -902,7 +886,7 @@ PathManipulator::ModifiersChanged(uint32 modifiers)
_SetModeForMousePos(fLastCanvasPos); _SetModeForMousePos(fLastCanvasPos);
} }
// HandleKeyDown
bool bool
PathManipulator::HandleKeyDown(uint32 key, uint32 modifiers, Command** _command) PathManipulator::HandleKeyDown(uint32 key, uint32 modifiers, Command** _command)
{ {
@@ -965,7 +949,7 @@ PathManipulator::HandleKeyDown(uint32 key, uint32 modifiers, Command** _command)
return result; return result;
} }
// HandleKeyUp
bool bool
PathManipulator::HandleKeyUp(uint32 key, uint32 modifiers, Command** _command) PathManipulator::HandleKeyUp(uint32 key, uint32 modifiers, Command** _command)
{ {
@@ -985,7 +969,7 @@ PathManipulator::HandleKeyUp(uint32 key, uint32 modifiers, Command** _command)
return handled; return handled;
} }
// UpdateCursor
bool bool
PathManipulator::UpdateCursor() PathManipulator::UpdateCursor()
{ {
@@ -1039,23 +1023,24 @@ PathManipulator::UpdateCursor()
return true; return true;
} }
// AttachedToView
void void
PathManipulator::AttachedToView(BView* view) PathManipulator::AttachedToView(BView* view)
{ {
fCanvasView = dynamic_cast<CanvasView*>(view); fCanvasView = dynamic_cast<CanvasView*>(view);
} }
// DetachedFromView
void void
PathManipulator::DetachedFromView(BView* view) PathManipulator::DetachedFromView(BView* view)
{ {
fCanvasView = NULL; fCanvasView = NULL;
} }
// #pragma mark - // #pragma mark -
// ObjectChanged
void void
PathManipulator::ObjectChanged(const Observable* object) PathManipulator::ObjectChanged(const Observable* object)
{ {
@@ -1070,16 +1055,17 @@ PathManipulator::ObjectChanged(const Observable* object)
_SetModeForMousePos(fLastCanvasPos); _SetModeForMousePos(fLastCanvasPos);
} }
// #pragma mark - // #pragma mark -
// PointAdded
void void
PathManipulator::PointAdded(int32 index) PathManipulator::PointAdded(int32 index)
{ {
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// PointRemoved
void void
PathManipulator::PointRemoved(int32 index) PathManipulator::PointRemoved(int32 index)
{ {
@@ -1087,28 +1073,28 @@ PathManipulator::PointRemoved(int32 index)
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// PointChanged
void void
PathManipulator::PointChanged(int32 index) PathManipulator::PointChanged(int32 index)
{ {
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// PathChanged
void void
PathManipulator::PathChanged() PathManipulator::PathChanged()
{ {
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// PathClosedChanged
void void
PathManipulator::PathClosedChanged() PathManipulator::PathClosedChanged()
{ {
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// PathReversed
void void
PathManipulator::PathReversed() PathManipulator::PathReversed()
{ {
@@ -1126,9 +1112,10 @@ PathManipulator::PathReversed()
ObjectChanged(fPath); ObjectChanged(fPath);
} }
// #pragma mark - // #pragma mark -
// ControlFlags
uint32 uint32
PathManipulator::ControlFlags() const PathManipulator::ControlFlags() const
{ {
@@ -1148,7 +1135,7 @@ PathManipulator::ControlFlags() const
return flags; return flags;
} }
// ReversePath
void void
PathManipulator::ReversePath() PathManipulator::ReversePath()
{ {
@@ -1164,9 +1151,10 @@ PathManipulator::ReversePath()
fPath->Reverse(); fPath->Reverse();
} }
// #pragma mark - // #pragma mark -
// _SetMode
void void
PathManipulator::_SetMode(uint32 mode) PathManipulator::_SetMode(uint32 mode)
{ {
@@ -1196,7 +1184,6 @@ PathManipulator::_SetMode(uint32 mode)
} }
// _SetTransformBox
void void
PathManipulator::_SetTransformBox(TransformPointsBox* transformBox) PathManipulator::_SetTransformBox(TransformPointsBox* transformBox)
{ {
@@ -1234,7 +1221,7 @@ PathManipulator::_SetTransformBox(TransformPointsBox* transformBox)
} }
} }
// _AddPoint
void void
PathManipulator::_AddPoint(BPoint where) PathManipulator::_AddPoint(BPoint where)
{ {
@@ -1250,7 +1237,7 @@ PathManipulator::_AddPoint(BPoint where)
} }
} }
// scale_point
BPoint BPoint
scale_point(BPoint a, BPoint b, float scale) scale_point(BPoint a, BPoint b, float scale)
{ {
@@ -1258,7 +1245,7 @@ scale_point(BPoint a, BPoint b, float scale)
a.y + (b.y - a.y) * scale); a.y + (b.y - a.y) * scale);
} }
// _InsertPoint
void void
PathManipulator::_InsertPoint(BPoint where, int32 index) PathManipulator::_InsertPoint(BPoint where, int32 index)
{ {
@@ -1309,14 +1296,14 @@ PathManipulator::_InsertPoint(BPoint where, int32 index)
} }
} }
// _SetInOutConnected
void void
PathManipulator::_SetInOutConnected(int32 index, bool connected) PathManipulator::_SetInOutConnected(int32 index, bool connected)
{ {
fPath->SetInOutConnected(index, connected); fPath->SetInOutConnected(index, connected);
} }
// _SetSharp
void void
PathManipulator::_SetSharp(int32 index) PathManipulator::_SetSharp(int32 index)
{ {
@@ -1325,7 +1312,7 @@ PathManipulator::_SetSharp(int32 index)
fPath->SetPoint(index, p, p, p, true); fPath->SetPoint(index, p, p, p, true);
} }
// _RemoveSelection
void void
PathManipulator::_RemoveSelection() PathManipulator::_RemoveSelection()
{ {
@@ -1345,7 +1332,6 @@ PathManipulator::_RemoveSelection()
} }
// _RemovePoint
void void
PathManipulator::_RemovePoint(int32 index) PathManipulator::_RemovePoint(int32 index)
{ {
@@ -1355,7 +1341,7 @@ PathManipulator::_RemovePoint(int32 index)
} }
} }
// _RemovePointIn
void void
PathManipulator::_RemovePointIn(int32 index) PathManipulator::_RemovePointIn(int32 index)
{ {
@@ -1366,7 +1352,7 @@ PathManipulator::_RemovePointIn(int32 index)
} }
} }
// _RemovePointOut
void void
PathManipulator::_RemovePointOut(int32 index) PathManipulator::_RemovePointOut(int32 index)
{ {
@@ -1377,7 +1363,7 @@ PathManipulator::_RemovePointOut(int32 index)
} }
} }
// _Delete
Command* Command*
PathManipulator::_Delete() PathManipulator::_Delete()
{ {
@@ -1403,9 +1389,10 @@ PathManipulator::_Delete()
return command; return command;
} }
// #pragma mark - // #pragma mark -
// _Select
void void
PathManipulator::_Select(BRect r) PathManipulator::_Select(BRect r)
{ {
@@ -1434,7 +1421,7 @@ PathManipulator::_Select(BRect r)
} }
} }
// _Select
void void
PathManipulator::_Select(int32 index, bool extend) PathManipulator::_Select(int32 index, bool extend)
{ {
@@ -1448,7 +1435,7 @@ PathManipulator::_Select(int32 index, bool extend)
_UpdateSelection(); _UpdateSelection();
} }
// _Select
void void
PathManipulator::_Select(const int32* indices, int32 count, bool extend) PathManipulator::_Select(const int32* indices, int32 count, bool extend)
{ {
@@ -1466,7 +1453,7 @@ PathManipulator::_Select(const int32* indices, int32 count, bool extend)
_UpdateSelection(); _UpdateSelection();
} }
// _Deselect
void void
PathManipulator::_Deselect(int32 index) PathManipulator::_Deselect(int32 index)
{ {
@@ -1476,32 +1463,34 @@ PathManipulator::_Deselect(int32 index)
} }
} }
// _ShiftSelection
void void
PathManipulator::_ShiftSelection(int32 startIndex, int32 direction) PathManipulator::_ShiftSelection(int32 startIndex, int32 direction)
{ {
int32 count = fSelection->CountItems(); int32 count = fSelection->CountItems();
if (count > 0) { if (count > 0) {
int32* selection = fSelection->Items();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
if (selection[i] >= startIndex) { int32 index = fSelection->IndexAt(i);
selection[i] += direction; if (index >= startIndex) {
fSelection->Remove(index);
fSelection->Add(index + direction);
} }
} }
} }
_UpdateSelection(); _UpdateSelection();
} }
// _IsSelected
bool bool
PathManipulator::_IsSelected(int32 index) const PathManipulator::_IsSelected(int32 index) const
{ {
return fSelection->Contains(index); return fSelection->Contains(index);
} }
// #pragma mark - // #pragma mark -
// _InvalidateCanvas
void void
PathManipulator::_InvalidateCanvas(BRect rect) const PathManipulator::_InvalidateCanvas(BRect rect) const
{ {
@@ -1510,7 +1499,7 @@ PathManipulator::_InvalidateCanvas(BRect rect) const
fCanvasView->Invalidate(rect); fCanvasView->Invalidate(rect);
} }
// _InvalidateHighlightPoints
void void
PathManipulator::_InvalidateHighlightPoints(int32 newIndex, uint32 newMode) PathManipulator::_InvalidateHighlightPoints(int32 newIndex, uint32 newMode)
{ {
@@ -1522,7 +1511,7 @@ PathManipulator::_InvalidateHighlightPoints(int32 newIndex, uint32 newMode)
_InvalidateCanvas(newRect); _InvalidateCanvas(newRect);
} }
// _UpdateSelection
void void
PathManipulator::_UpdateSelection() const PathManipulator::_UpdateSelection() const
{ {
@@ -1532,7 +1521,7 @@ PathManipulator::_UpdateSelection() const
} }
} }
// _ControlPointRect
BRect BRect
PathManipulator::_ControlPointRect() const PathManipulator::_ControlPointRect() const
{ {
@@ -1541,7 +1530,7 @@ PathManipulator::_ControlPointRect() const
return r; return r;
} }
// _ControlPointRect
BRect BRect
PathManipulator::_ControlPointRect(int32 index, uint32 mode) const PathManipulator::_ControlPointRect(int32 index, uint32 mode) const
{ {
@@ -1581,9 +1570,10 @@ PathManipulator::_ControlPointRect(int32 index, uint32 mode) const
return rect; return rect;
} }
// #pragma mark - // #pragma mark -
// _SetModeForMousePos
void void
PathManipulator::_SetModeForMousePos(BPoint where) PathManipulator::_SetModeForMousePos(BPoint where)
{ {
@@ -1679,9 +1669,10 @@ PathManipulator::_SetModeForMousePos(BPoint where)
} }
} }
// #pragma mark - // #pragma mark -
// _Nudge
void void
PathManipulator::_Nudge(BPoint direction) PathManipulator::_Nudge(BPoint direction)
{ {
@@ -1730,7 +1721,7 @@ PathManipulator::_Nudge(BPoint direction)
_SetModeForMousePos(fLastCanvasPos); _SetModeForMousePos(fLastCanvasPos);
} }
// _FinishNudging
Command* Command*
PathManipulator::_FinishNudging() PathManipulator::_FinishNudging()
{ {
@@ -1747,5 +1738,3 @@ PathManipulator::_FinishNudging()
return command; return command;
} }