aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj12
-rw-r--r--gtk/deps.mak3
-rw-r--r--gtk/makefile1
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.pro1
-rw-r--r--qt/ScintillaEditBase/ScintillaEditBase.pro1
-rw-r--r--src/Geometry.cxx97
-rw-r--r--src/Geometry.h101
-rw-r--r--win32/deps.mak3
-rw-r--r--win32/makefile1
-rw-r--r--win32/nmdeps.mak3
-rw-r--r--win32/scintilla.mak1
11 files changed, 217 insertions, 7 deletions
diff --git a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
index 5ae456664..d0e7a0c8d 100644
--- a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
+++ b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
@@ -87,6 +87,9 @@
286F8E6425F84F7400EC8D60 /* ILexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 286F8E6025F84F7400EC8D60 /* ILexer.h */; settings = {ATTRIBUTES = (Public, ); }; };
286F8E6525F84F7400EC8D60 /* ILoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 286F8E6125F84F7400EC8D60 /* ILoader.h */; settings = {ATTRIBUTES = (Public, ); }; };
286F8E6625F84F7400EC8D60 /* Scintilla.h in Headers */ = {isa = PBXBuildFile; fileRef = 286F8E6225F84F7400EC8D60 /* Scintilla.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 286F8EDE260448C300EC8D60 /* Platform.h in Headers */ = {isa = PBXBuildFile; fileRef = 286F8EDB260448C300EC8D60 /* Platform.h */; };
+ 286F8EDF260448C300EC8D60 /* Geometry.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 286F8EDC260448C300EC8D60 /* Geometry.cxx */; };
+ 286F8EE0260448C300EC8D60 /* Geometry.h in Headers */ = {isa = PBXBuildFile; fileRef = 286F8EDD260448C300EC8D60 /* Geometry.h */; };
287F3C6A246F90240040E76F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287F3C69246F90240040E76F /* Cocoa.framework */; };
287F3C6C246F90300040E76F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287F3C6B246F90300040E76F /* QuartzCore.framework */; };
28EA9CAE255894B4007710C4 /* CharacterCategory.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 28EA9CAA255894B4007710C4 /* CharacterCategory.cxx */; };
@@ -177,6 +180,9 @@
286F8E6025F84F7400EC8D60 /* ILexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ILexer.h; path = ../../include/ILexer.h; sourceTree = "<group>"; };
286F8E6125F84F7400EC8D60 /* ILoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ILoader.h; path = ../../include/ILoader.h; sourceTree = "<group>"; };
286F8E6225F84F7400EC8D60 /* Scintilla.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scintilla.h; path = ../../include/Scintilla.h; sourceTree = "<group>"; };
+ 286F8EDB260448C300EC8D60 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = ../../src/Platform.h; sourceTree = "<group>"; };
+ 286F8EDC260448C300EC8D60 /* Geometry.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Geometry.cxx; path = ../../src/Geometry.cxx; sourceTree = "<group>"; };
+ 286F8EDD260448C300EC8D60 /* Geometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Geometry.h; path = ../../src/Geometry.h; sourceTree = "<group>"; };
287F3C41246F8DC70040E76F /* Scintilla.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Scintilla.framework; sourceTree = BUILT_PRODUCTS_DIR; };
287F3C69246F90240040E76F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
287F3C6B246F90300040E76F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
@@ -254,6 +260,8 @@
2829371324E2D58600C84BA2 /* EditView.h */,
282936EC24E2D58400C84BA2 /* ElapsedPeriod.h */,
2829372024E2D58700C84BA2 /* FontQuality.h */,
+ 286F8EDC260448C300EC8D60 /* Geometry.cxx */,
+ 286F8EDD260448C300EC8D60 /* Geometry.h */,
286F8E6025F84F7400EC8D60 /* ILexer.h */,
286F8E6125F84F7400EC8D60 /* ILoader.h */,
282936F624E2D58400C84BA2 /* Indicator.cxx */,
@@ -268,6 +276,7 @@
2829371F24E2D58700C84BA2 /* Partitioning.h */,
2829371024E2D58500C84BA2 /* PerLine.cxx */,
282936FA24E2D58400C84BA2 /* PerLine.h */,
+ 286F8EDB260448C300EC8D60 /* Platform.h */,
282936F824E2D58400C84BA2 /* Position.h */,
2829370224E2D58500C84BA2 /* PositionCache.cxx */,
282936EE24E2D58400C84BA2 /* PositionCache.h */,
@@ -351,6 +360,7 @@
2829373224E2D58800C84BA2 /* KeyMap.h in Headers */,
2829376324E2D58800C84BA2 /* FontQuality.h in Headers */,
2829373E24E2D58800C84BA2 /* Indicator.h in Headers */,
+ 286F8EDE260448C300EC8D60 /* Platform.h in Headers */,
2829375C24E2D58800C84BA2 /* CellBuffer.h in Headers */,
2829373F24E2D58800C84BA2 /* UniConversion.h in Headers */,
2829373D24E2D58800C84BA2 /* PerLine.h in Headers */,
@@ -391,6 +401,7 @@
2829374D24E2D58800C84BA2 /* AutoComplete.h in Headers */,
2829374124E2D58800C84BA2 /* CharClassify.h in Headers */,
2829373124E2D58800C84BA2 /* PositionCache.h in Headers */,
+ 286F8EE0260448C300EC8D60 /* Geometry.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -493,6 +504,7 @@
28EA9CAE255894B4007710C4 /* CharacterCategory.cxx in Sources */,
2829374024E2D58800C84BA2 /* XPM.cxx in Sources */,
2829374B24E2D58800C84BA2 /* Decoration.cxx in Sources */,
+ 286F8EDF260448C300EC8D60 /* Geometry.cxx in Sources */,
2829373624E2D58800C84BA2 /* UniqueString.cxx in Sources */,
282936E824E2D55D00C84BA2 /* ScintillaView.mm in Sources */,
2829376924E2D58800C84BA2 /* CellBuffer.cxx in Sources */,
diff --git a/gtk/deps.mak b/gtk/deps.mak
index f446b6dd1..749a3a0d1 100644
--- a/gtk/deps.mak
+++ b/gtk/deps.mak
@@ -288,6 +288,9 @@ EditView.o: \
../src/MarginView.h \
../src/EditView.h \
../src/ElapsedPeriod.h
+Geometry.o: \
+ ../src/Geometry.cxx \
+ ../src/Geometry.h
Indicator.o: \
../src/Indicator.cxx \
../src/Debugging.h \
diff --git a/gtk/makefile b/gtk/makefile
index 862276097..a820e1476 100644
--- a/gtk/makefile
+++ b/gtk/makefile
@@ -138,6 +138,7 @@ SRC_OBJS = \
EditModel.o \
Editor.o \
EditView.o \
+ Geometry.o \
Indicator.o \
KeyMap.o \
LineMarker.o \
diff --git a/qt/ScintillaEdit/ScintillaEdit.pro b/qt/ScintillaEdit/ScintillaEdit.pro
index 244352d2d..36ffdd017 100644
--- a/qt/ScintillaEdit/ScintillaEdit.pro
+++ b/qt/ScintillaEdit/ScintillaEdit.pro
@@ -35,6 +35,7 @@ SOURCES += \
../../src/LineMarker.cxx \
../../src/KeyMap.cxx \
../../src/Indicator.cxx \
+ ../../src/Geometry.cxx \
../../src/EditView.cxx \
../../src/Editor.cxx \
../../src/EditModel.cxx \
diff --git a/qt/ScintillaEditBase/ScintillaEditBase.pro b/qt/ScintillaEditBase/ScintillaEditBase.pro
index c39b0f1f6..e867418f9 100644
--- a/qt/ScintillaEditBase/ScintillaEditBase.pro
+++ b/qt/ScintillaEditBase/ScintillaEditBase.pro
@@ -33,6 +33,7 @@ SOURCES += \
../../src/LineMarker.cxx \
../../src/KeyMap.cxx \
../../src/Indicator.cxx \
+ ../../src/Geometry.cxx \
../../src/EditView.cxx \
../../src/Editor.cxx \
../../src/EditModel.cxx \
diff --git a/src/Geometry.cxx b/src/Geometry.cxx
new file mode 100644
index 000000000..68ce1f628
--- /dev/null
+++ b/src/Geometry.cxx
@@ -0,0 +1,97 @@
+// Scintilla source code edit control
+/** @file Geometry.cxx
+ ** Helper functions for geometric calculations.
+ **/
+// Copyright 2020 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <cmath>
+
+#include <algorithm>
+
+#include "Geometry.h"
+
+namespace Scintilla {
+
+PRectangle Clamp(PRectangle rc, Edge edge, XYPOSITION position) noexcept {
+ switch (edge) {
+ case Edge::left:
+ return PRectangle(std::clamp(position, rc.left, rc.right), rc.top, rc.right, rc.bottom);
+ case Edge::top:
+ return PRectangle(rc.left, std::clamp(position, rc.top, rc.bottom), rc.right, rc.bottom);
+ case Edge::right:
+ return PRectangle(rc.left, rc.top, std::clamp(position, rc.left, rc.right), rc.bottom);
+ case Edge::bottom:
+ default:
+ return PRectangle(rc.left, rc.top, rc.right, std::clamp(position, rc.top, rc.bottom));
+ }
+}
+
+PRectangle Side(PRectangle rc, Edge edge, XYPOSITION size) noexcept {
+ switch (edge) {
+ case Edge::left:
+ return PRectangle(rc.left, rc.top, std::min(rc.left + size, rc.right), rc.bottom);
+ case Edge::top:
+ return PRectangle(rc.left, rc.top, rc.right, std::min(rc.top + size, rc.bottom));
+ case Edge::right:
+ return PRectangle(std::max(rc.left, rc.right - size), rc.top, rc.right, rc.bottom);
+ case Edge::bottom:
+ default:
+ return PRectangle(rc.left, std::max(rc.top, rc.bottom - size), rc.right, rc.bottom);
+ }
+}
+
+Interval Intersection(Interval a, Interval b) noexcept {
+ const XYPOSITION leftMax = std::max(a.left, b.left);
+ const XYPOSITION rightMin = std::min(a.right, b.right);
+ // If the result would have a negative width. make empty instead.
+ const XYPOSITION rightResult = (rightMin >= leftMax) ? rightMin : leftMax;
+ return { leftMax, rightResult };
+}
+
+PRectangle Intersection(PRectangle rc, Interval horizontalBounds) noexcept {
+ const Interval intersection = Intersection(HorizontalBounds(rc), horizontalBounds);
+ return PRectangle(intersection.left, rc.top, intersection.right, rc.bottom);
+}
+
+Interval HorizontalBounds(PRectangle rc) noexcept {
+ return { rc.left, rc.right };
+}
+
+XYPOSITION PixelAlign(XYPOSITION xy, int pixelDivisions) noexcept {
+ return std::round(xy * pixelDivisions) / pixelDivisions;
+}
+
+XYPOSITION PixelAlignFloor(XYPOSITION xy, int pixelDivisions) noexcept {
+ return std::floor(xy * pixelDivisions) / pixelDivisions;
+}
+
+Point PixelAlign(const Point &pt, int pixelDivisions) noexcept {
+ return Point(
+ std::round(pt.x * pixelDivisions) / pixelDivisions,
+ std::round(pt.y * pixelDivisions) / pixelDivisions);
+}
+
+PRectangle PixelAlign(const PRectangle &rc, int pixelDivisions) noexcept {
+ // Move left and right side to nearest pixel to avoid blurry visuals.
+ // The top and bottom should be integers but floor them to make sure.
+ // `pixelDivisions` is commonly 1 except for 'retina' displays where it is 2.
+ // On retina displays, the positions should be moved to the nearest device
+ // pixel which is the nearest half logical pixel.
+ return PRectangle(
+ std::round(rc.left * pixelDivisions) / pixelDivisions,
+ PixelAlignFloor(rc.top, pixelDivisions),
+ std::round(rc.right * pixelDivisions) / pixelDivisions,
+ PixelAlignFloor(rc.bottom, pixelDivisions));
+}
+
+PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept {
+ // Move left and right side to extremes (floor(left) ceil(right)) to avoid blurry visuals.
+ return PRectangle(
+ std::floor(rc.left * pixelDivisions) / pixelDivisions,
+ std::floor(rc.top * pixelDivisions) / pixelDivisions,
+ std::ceil(rc.right * pixelDivisions) / pixelDivisions,
+ std::floor(rc.bottom * pixelDivisions) / pixelDivisions);
+}
+
+}
diff --git a/src/Geometry.h b/src/Geometry.h
index 35702a468..bab50d502 100644
--- a/src/Geometry.h
+++ b/src/Geometry.h
@@ -35,6 +35,10 @@ public:
return Point(static_cast<XYPOSITION>(x_), static_cast<XYPOSITION>(y_));
}
+ constexpr bool operator==(Point other) const noexcept {
+ return (x == other.x) && (y == other.y);
+ }
+
constexpr bool operator!=(Point other) const noexcept {
return (x != other.x) || (y != other.y);
}
@@ -50,9 +54,24 @@ public:
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
};
-struct Interval {
+
+/**
+ * A geometric interval class.
+ */
+class Interval {
+public:
XYPOSITION left;
XYPOSITION right;
+ constexpr bool operator==(const Interval &other) const noexcept {
+ return (left == other.left) && (right == other.right);
+ }
+ constexpr XYPOSITION Width() const noexcept { return right - left; }
+ constexpr bool Empty() const noexcept {
+ return Width() <= 0;
+ }
+ constexpr bool Intersects(Interval other) const noexcept {
+ return (right > other.left) && (left < other.right);
+ }
};
/**
@@ -105,6 +124,15 @@ public:
right += xDelta;
bottom += yDelta;
}
+
+ constexpr PRectangle Inset(XYPOSITION delta) const noexcept {
+ return PRectangle(left + delta, top + delta, right - delta, bottom - delta);
+ }
+
+ constexpr Point Centre() const noexcept {
+ return Point((left + right) / 2, (top + bottom) / 2);
+ }
+
constexpr XYPOSITION Width() const noexcept { return right - left; }
constexpr XYPOSITION Height() const noexcept { return bottom - top; }
constexpr bool Empty() const noexcept {
@@ -112,6 +140,23 @@ public:
}
};
+enum class Edge { left, top, bottom, right };
+
+PRectangle Clamp(PRectangle rc, Edge edge, XYPOSITION position) noexcept;
+PRectangle Side(PRectangle rc, Edge edge, XYPOSITION size) noexcept;
+
+Interval Intersection(Interval a, Interval b) noexcept;
+PRectangle Intersection(PRectangle rc, Interval horizontalBounds) noexcept;
+Interval HorizontalBounds(PRectangle rc) noexcept;
+
+XYPOSITION PixelAlign(XYPOSITION xy, int pixelDivisions) noexcept;
+XYPOSITION PixelAlignFloor(XYPOSITION xy, int pixelDivisions) noexcept;
+
+Point PixelAlign(const Point &pt, int pixelDivisions) noexcept;
+
+PRectangle PixelAlign(const PRectangle &rc, int pixelDivisions) noexcept;
+PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept;
+
/**
* Holds an RGB colour with 8 bits for each component.
*/
@@ -165,11 +210,7 @@ public:
constexpr explicit ColourAlpha(int co_ = 0) noexcept : ColourDesired(co_) {
}
- constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue) noexcept :
- ColourDesired(red | (green << 8) | (blue << 16)) {
- }
-
- constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) noexcept :
+ constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha=0xff) noexcept :
ColourDesired(red | (green << 8) | (blue << 16) | (alpha << 24)) {
}
@@ -177,6 +218,10 @@ public:
ColourDesired(cd.AsInteger() | (alpha << 24)) {
}
+ constexpr ColourAlpha(ColourDesired cd) noexcept :
+ ColourDesired(cd.AsInteger() | (0xff << 24)) {
+ }
+
constexpr ColourDesired GetColour() const noexcept {
return ColourDesired(AsInteger() & 0xffffff);
}
@@ -189,6 +234,10 @@ public:
return GetAlpha() / componentMaximum;
}
+ constexpr bool IsOpaque() const noexcept {
+ return GetAlpha() == 0xff;
+ }
+
constexpr ColourAlpha MixedWith(ColourAlpha other) const noexcept {
const unsigned int red = (GetRed() + other.GetRed()) / 2;
const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
@@ -199,13 +248,51 @@ public:
};
/**
+* Holds an RGBA colour and stroke width to stroke a shape.
+*/
+class Stroke {
+public:
+ ColourAlpha colourStroke;
+ XYPOSITION widthStroke;
+ constexpr Stroke(ColourAlpha colourStroke_, XYPOSITION widthStroke_=1.0f) noexcept :
+ colourStroke(colourStroke_), widthStroke(widthStroke_) {
+ }
+};
+
+/**
+* Holds an RGBA colour to fill a shape.
+*/
+class Fill {
+public:
+ ColourAlpha colourFill;
+ constexpr Fill(ColourAlpha colourFill_) noexcept :
+ colourFill(colourFill_) {
+ }
+};
+
+/**
+* Holds a pair of RGBA colours and stroke width to fill and stroke a shape.
+*/
+class FillStroke {
+public:
+ Fill fill;
+ Stroke stroke;
+ constexpr FillStroke(ColourAlpha colourFill_, ColourAlpha colourStroke_, XYPOSITION widthStroke_=1.0f) noexcept :
+ fill(colourFill_), stroke(colourStroke_, widthStroke_) {
+ }
+ constexpr FillStroke(ColourAlpha colourBoth, XYPOSITION widthStroke_=1.0f) noexcept :
+ fill(colourBoth), stroke(colourBoth, widthStroke_) {
+ }
+};
+
+/**
* Holds an element of a gradient with an RGBA colour and a relative position.
*/
class ColourStop {
public:
float position;
ColourAlpha colour;
- ColourStop(float position_, ColourAlpha colour_) noexcept :
+ constexpr ColourStop(float position_, ColourAlpha colour_) noexcept :
position(position_), colour(colour_) {
}
};
diff --git a/win32/deps.mak b/win32/deps.mak
index 71978a153..af07609e1 100644
--- a/win32/deps.mak
+++ b/win32/deps.mak
@@ -254,6 +254,9 @@ EditView.o: \
../src/MarginView.h \
../src/EditView.h \
../src/ElapsedPeriod.h
+Geometry.o: \
+ ../src/Geometry.cxx \
+ ../src/Geometry.h
Indicator.o: \
../src/Indicator.cxx \
../src/Debugging.h \
diff --git a/win32/makefile b/win32/makefile
index 5e005fe24..7dd2604bb 100644
--- a/win32/makefile
+++ b/win32/makefile
@@ -96,6 +96,7 @@ SRC_OBJS = \
EditModel.o \
Editor.o \
EditView.o \
+ Geometry.o \
Indicator.o \
KeyMap.o \
LineMarker.o \
diff --git a/win32/nmdeps.mak b/win32/nmdeps.mak
index 601f10acd..d9ba665f5 100644
--- a/win32/nmdeps.mak
+++ b/win32/nmdeps.mak
@@ -254,6 +254,9 @@ $(DIR_O)/EditView.obj: \
../src/MarginView.h \
../src/EditView.h \
../src/ElapsedPeriod.h
+$(DIR_O)/Geometry.obj: \
+ ../src/Geometry.cxx \
+ ../src/Geometry.h
$(DIR_O)/Indicator.obj: \
../src/Indicator.cxx \
../src/Debugging.h \
diff --git a/win32/scintilla.mak b/win32/scintilla.mak
index 7a7fb89da..edb0c7de8 100644
--- a/win32/scintilla.mak
+++ b/win32/scintilla.mak
@@ -89,6 +89,7 @@ SRC_OBJS=\
$(DIR_O)\EditModel.obj \
$(DIR_O)\Editor.obj \
$(DIR_O)\EditView.obj \
+ $(DIR_O)\Geometry.obj \
$(DIR_O)\Indicator.obj \
$(DIR_O)\KeyMap.obj \
$(DIR_O)\LineMarker.obj \