// Scintilla source code edit control /** @file Indicator.cxx ** Defines the style of indicators which are text decorations such as underlining. **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include #include #include #include "ScintillaTypes.h" #include "Debugging.h" #include "Geometry.h" #include "Platform.h" #include "Indicator.h" #include "XPM.h" using namespace Scintilla; using namespace Scintilla::Internal; void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, const PRectangle &rcCharacter, State state, int value) const { StyleAndColour sacDraw = sacNormal; if (FlagSet(Flags(), IndicFlag::ValueFore)) { sacDraw.fore = ColourRGBA::FromRGB(value & static_cast(IndicValue::Mask)); } if (state == State::hover) { sacDraw = sacHover; } const int pixelDivisions = surface->PixelDivisions(); const XYPOSITION halfWidth = strokeWidth / 2.0f; const PRectangle rcAligned(PixelAlignOutside(rc, pixelDivisions)); PRectangle rcFullHeightAligned = PixelAlignOutside(rcLine, pixelDivisions); rcFullHeightAligned.left = rcAligned.left; rcFullHeightAligned.right = rcAligned.right; const XYPOSITION ymid = PixelAlign(rc.Centre().y, pixelDivisions); // This is a reasonable clip for indicators beneath text like underlines PRectangle rcClip = rcAligned; rcClip.bottom = rcFullHeightAligned.bottom; switch (sacDraw.style) { case IndicatorStyle::Squiggle: { surface->SetClip(rcClip); XYPOSITION x = rcAligned.left + halfWidth; const XYPOSITION top = rcAligned.top + halfWidth; const XYPOSITION xLast = rcAligned.right + halfWidth; XYPOSITION y = 0; std::vector pts; const XYPOSITION pitch = 1 + strokeWidth; pts.emplace_back(x, top + y); while (x < xLast) { x += pitch; y = pitch - y; pts.emplace_back(x, top + y); } surface->PolyLine(pts.data(), std::size(pts), Stroke(sacDraw.fore, strokeWidth)); surface->PopClip(); } break; case IndicatorStyle::SquigglePixmap: { const PRectangle rcSquiggle = PixelAlign(rc, 1); const int width = std::min(4000, static_cast(rcSquiggle.Width())); RGBAImage image(width, 3, 1.0, nullptr); constexpr unsigned int alphaFull = 0xff; constexpr unsigned int alphaSide = 0x2f; constexpr unsigned int alphaSide2 = 0x5f; for (int x = 0; x < width; x++) { if (x%2) { // Two halfway columns have a full pixel in middle flanked by light pixels image.SetPixel(x, 0, ColourRGBA(sacDraw.fore, alphaSide)); image.SetPixel(x, 1, ColourRGBA(sacDraw.fore, alphaFull)); image.SetPixel(x, 2, ColourRGBA(sacDraw.fore, alphaSide)); } else { // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre image.SetPixel(x, (x % 4) ? 0 : 2, ColourRGBA(sacDraw.fore, alphaFull)); image.SetPixel(x, 1, ColourRGBA(sacDraw.fore, alphaSide2)); } } surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels()); } break; case IndicatorStyle::SquiggleLow: { std::vector pts; const XYPOSITION top = rcAligned.top + halfWidth; int y = 0; XYPOSITION x = std::round(rcAligned.left) + halfWidth; pts.emplace_back(x, top + y); const XYPOSITION pitch = 2 + strokeWidth; x += pitch; while (x < rcAligned.right) { pts.emplace_back(x - 1, top + y); y = 1 - y; pts.emplace_back(x, top + y); x += pitch; } pts.emplace_back(rcAligned.right, top + y); surface->PolyLine(pts.data(), std::size(pts), Stroke(sacDraw.fore, strokeWidth)); } break; case IndicatorStyle::TT: { surface->SetClip(rcClip); const XYPOSITION yLine = ymid; XYPOSITION x = rcAligned.left + 5.0f; const XYPOSITION pitch = 4 + strokeWidth; while (x < rc.right + pitch) { const PRectangle line(x-pitch, yLine, x, yLine + strokeWidth); surface->FillRectangle(line, sacDraw.fore); const PRectangle tail(x - 2 - strokeWidth, yLine + strokeWidth, x - 2, yLine + strokeWidth * 2); surface->FillRectangle(tail, sacDraw.fore); x++; x += pitch; } surface->PopClip(); } break; case IndicatorStyle::Diagonal: { surface->SetClip(rcClip); XYPOSITION x = rcAligned.left + halfWidth; const XYPOSITION top = rcAligned.top + halfWidth; const XYPOSITION pitch = 3 + strokeWidth; while (x < rc.right) { const XYPOSITION endX = x+3; const XYPOSITION endY = top - 1; surface->LineDraw(Point(x, top + 2), Point(endX, endY), Stroke(sacDraw.fore, strokeWidth)); x += pitch; } surface->PopClip(); } break; case IndicatorStyle::Strike: { const XYPOSITION yStrike = std::round(rcLine.Centre().y); const PRectangle rcStrike( rcAligned.left, yStrike, rcAligned.right, yStrike + strokeWidth); surface->FillRectangle(rcStrike, sacDraw.fore); } break; case IndicatorStyle::Hidden: case IndicatorStyle::TextFore: // Draw nothing break; case IndicatorStyle::Box: { PRectangle rcBox = rcFullHeightAligned; rcBox.top = rcBox.top + 1.0f; rcBox.bottom = ymid + 1.0f; surface->RectangleFrame(rcBox, Stroke(ColourRGBA(sacDraw.fore, outlineAlpha), strokeWidth)); } break; case IndicatorStyle::RoundBox: case IndicatorStyle::StraightBox: case IndicatorStyle::FullBox: { PRectangle rcBox = rcFullHeightAligned; if (sacDraw.style != IndicatorStyle::FullBox) rcBox.top = rcBox.top + 1; surface->AlphaRectangle(rcBox, (sacDraw.style == IndicatorStyle::RoundBox) ? 1.0f : 0.0f, FillStroke(ColourRGBA(sacDraw.fore, fillAlpha), ColourRGBA(sacDraw.fore, outlineAlpha), strokeWidth)); } break; case IndicatorStyle::Gradient: case IndicatorStyle::GradientCentre: { PRectangle rcBox = rcFullHeightAligned; rcBox.top = rcBox.top + 1; const Surface::GradientOptions options = Surface::GradientOptions::topToBottom; const ColourRGBA start(sacDraw.fore, fillAlpha); const ColourRGBA end(sacDraw.fore, 0); std::vector stops; switch (sacDraw.style) { case IndicatorStyle::Gradient: stops.push_back(ColourStop(0.0, start)); stops.push_back(ColourStop(1.0, end)); break; case IndicatorStyle::GradientCentre: stops.push_back(ColourStop(0.0, end)); stops.push_back(ColourStop(0.5, start)); stops.push_back(ColourStop(1.0, end)); break; default: break; } surface->GradientRectangle(rcBox, stops, options); } break; case IndicatorStyle::DotBox: { PRectangle rcBox = rcFullHeightAligned; rcBox.top = rcBox.top + 1; // Cap width at 4000 to avoid large allocations when mistakes made const int width = std::min(static_cast(rcBox.Width()), 4000); const int height = static_cast(rcBox.Height()); RGBAImage image(width, height, 1.0, nullptr); // Draw horizontal lines top and bottom for (int x=0; xDrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels()); } break; case IndicatorStyle::Dash: { XYPOSITION x = std::floor(rc.left); const XYPOSITION widthDash = 3 + std::round(strokeWidth); while (x < rc.right) { const PRectangle rcDash = PRectangle(x, ymid, x + widthDash, ymid + std::round(strokeWidth)); surface->FillRectangle(rcDash, sacDraw.fore); x += 3 + widthDash; } } break; case IndicatorStyle::Dots: { const XYPOSITION widthDot = std::round(strokeWidth); XYPOSITION x = std::floor(rc.left); while (x < rc.right) { const PRectangle rcDot = PRectangle(x, ymid, x + widthDot, ymid + widthDot); surface->FillRectangle(rcDot, sacDraw.fore); x += widthDot * 2HTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="Indicator.cxx" Content-Disposition: inline; filename="Indicator.cxx" Content-Disposition: inline; filename="Indicator.cxx" Content-Length: 10235 Content-Length: 10235 Content-Length: 10235 Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Date: Mon, 20 Oct 2025 23:24:07 UTC ETag: "5c15caeb6dbfef7223578823286dce4a2ecfa00f" ETag: "5c15caeb6dbfef7223578823286dce4a2ecfa00f" ETag: "5c15caeb6dbfef7223578823286dce4a2ecfa00f" Expires: Thu, 18 Oct 2035 23:24:07 GMT Expires: Thu, 18 Oct 2035 23:24:07 GMT Expires: Thu, 18 Oct 2035 23:24:08 GMT Last-Modified: Mon, 20 Oct 2025 23:24:07 GMT Last-Modified: Mon, 20 Oct 2025 23:24:07 GMT Last-Modified: Mon, 20 Oct 2025 23:24:08 GMT Server: OpenBSD httpd Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff // Scintilla source code edit control /** @file Indicator.cxx ** Defines the style of indicators which are text decorations such as underlining. **/ // Copyright 1998-2001 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include #include #include #include "ScintillaTypes.h" #include "Debugging.h" #include "Geometry.h" #include "Platform.h" #include "Indicator.h" #include "XPM.h" using namespace Scintilla; using namespace Scintilla::Internal; void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, const PRectangle &rcCharacter, State state, int value) const { StyleAndColour sacDraw = sacNo