Update Scintilla to 3.4.2 pre-release
[geany-mirror.git] / scintilla / src / Indicator.cxx
blob63735d48046a4dd4cef65483e5e0568ff6871908
1 // Scintilla source code edit control
2 /** @file Indicator.cxx
3 ** Defines the style of indicators which are text decorations such as underlining.
4 **/
5 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <vector>
9 #include <map>
11 #include "Platform.h"
13 #include "Scintilla.h"
14 #include "XPM.h"
15 #include "Indicator.h"
17 #ifdef SCI_NAMESPACE
18 using namespace Scintilla;
19 #endif
21 static PRectangle PixelGridAlign(const PRectangle &rc) {
22 // Move left and right side to nearest pixel to avoid blurry visuals
23 return PRectangle::FromInts(int(rc.left + 0.5), int(rc.top), int(rc.right + 0.5), int(rc.bottom));
26 void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
27 surface->PenColour(fore);
28 int ymid = static_cast<int>(rc.bottom + rc.top) / 2;
29 if (style == INDIC_SQUIGGLE) {
30 int x = int(rc.left+0.5);
31 int xLast = int(rc.right+0.5);
32 int y = 0;
33 surface->MoveTo(x, static_cast<int>(rc.top) + y);
34 while (x < xLast) {
35 if ((x + 2) > xLast) {
36 if (xLast > x)
37 y = 1;
38 x = xLast;
39 } else {
40 x += 2;
41 y = 2 - y;
43 surface->LineTo(x, static_cast<int>(rc.top) + y);
45 } else if (style == INDIC_SQUIGGLEPIXMAP) {
46 PRectangle rcSquiggle = PixelGridAlign(rc);
48 int width = Platform::Minimum(4000, static_cast<int>(rcSquiggle.Width()));
49 RGBAImage image(width, 3, 1.0, 0);
50 enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
51 for (int x = 0; x < width; x++) {
52 if (x%2) {
53 // Two halfway columns have a full pixel in middle flanked by light pixels
54 image.SetPixel(x, 0, fore, alphaSide);
55 image.SetPixel(x, 1, fore, alphaFull);
56 image.SetPixel(x, 2, fore, alphaSide);
57 } else {
58 // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
59 image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
60 image.SetPixel(x, 1, fore, alphaSide2);
63 surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
64 } else if (style == INDIC_SQUIGGLELOW) {
65 surface->MoveTo(static_cast<int>(rc.left), static_cast<int>(rc.top));
66 int x = static_cast<int>(rc.left) + 3;
67 int y = 0;
68 while (x < rc.right) {
69 surface->LineTo(x - 1, static_cast<int>(rc.top) + y);
70 y = 1 - y;
71 surface->LineTo(x, static_cast<int>(rc.top) + y);
72 x += 3;
74 surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rc.top) + y); // Finish the line
75 } else if (style == INDIC_TT) {
76 surface->MoveTo(static_cast<int>(rc.left), ymid);
77 int x = static_cast<int>(rc.left) + 5;
78 while (x < rc.right) {
79 surface->LineTo(x, ymid);
80 surface->MoveTo(x-3, ymid);
81 surface->LineTo(x-3, ymid+2);
82 x++;
83 surface->MoveTo(x, ymid);
84 x += 5;
86 surface->LineTo(static_cast<int>(rc.right), ymid); // Finish the line
87 if (x - 3 <= rc.right) {
88 surface->MoveTo(x-3, ymid);
89 surface->LineTo(x-3, ymid+2);
91 } else if (style == INDIC_DIAGONAL) {
92 int x = static_cast<int>(rc.left);
93 while (x < rc.right) {
94 surface->MoveTo(x, static_cast<int>(rc.top) + 2);
95 int endX = x+3;
96 int endY = static_cast<int>(rc.top) - 1;
97 if (endX > rc.right) {
98 endY += endX - static_cast<int>(rc.right);
99 endX = static_cast<int>(rc.right);
101 surface->LineTo(endX, endY);
102 x += 4;
104 } else if (style == INDIC_STRIKE) {
105 surface->MoveTo(static_cast<int>(rc.left), static_cast<int>(rc.top) - 4);
106 surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rc.top) - 4);
107 } else if (style == INDIC_HIDDEN) {
108 // Draw nothing
109 } else if (style == INDIC_BOX) {
110 surface->MoveTo(static_cast<int>(rc.left), ymid + 1);
111 surface->LineTo(static_cast<int>(rc.right), ymid + 1);
112 surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rcLine.top) + 1);
113 surface->LineTo(static_cast<int>(rc.left), static_cast<int>(rcLine.top) + 1);
114 surface->LineTo(static_cast<int>(rc.left), ymid + 1);
115 } else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
116 PRectangle rcBox = rcLine;
117 rcBox.top = rcLine.top + 1;
118 rcBox.left = rc.left;
119 rcBox.right = rc.right;
120 surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
121 } else if (style == INDIC_DOTBOX) {
122 PRectangle rcBox = PixelGridAlign(rc);
123 rcBox.top = rcLine.top + 1;
124 rcBox.bottom = rcLine.bottom;
125 // Cap width at 4000 to avoid large allocations when mistakes made
126 int width = Platform::Minimum(static_cast<int>(rcBox.Width()), 4000);
127 RGBAImage image(width, static_cast<int>(rcBox.Height()), 1.0, 0);
128 // Draw horizontal lines top and bottom
129 for (int x=0; x<width; x++) {
130 for (int y = 0; y<static_cast<int>(rcBox.Height()); y += static_cast<int>(rcBox.Height()) - 1) {
131 image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
134 // Draw vertical lines left and right
135 for (int y = 1; y<static_cast<int>(rcBox.Height()); y++) {
136 for (int x=0; x<width; x += width-1) {
137 image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
140 surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
141 } else if (style == INDIC_DASH) {
142 int x = static_cast<int>(rc.left);
143 while (x < rc.right) {
144 surface->MoveTo(x, ymid);
145 surface->LineTo(Platform::Minimum(x + 4, static_cast<int>(rc.right)), ymid);
146 x += 7;
148 } else if (style == INDIC_DOTS) {
149 int x = static_cast<int>(rc.left);
150 while (x < static_cast<int>(rc.right)) {
151 PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1);
152 surface->FillRectangle(rcDot, fore);
153 x += 2;
155 } else if (style == INDIC_COMPOSITIONTHICK) {
156 PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom);
157 surface->FillRectangle(rcComposition, fore);
158 } else { // Either INDIC_PLAIN or unknown
159 surface->MoveTo(static_cast<int>(rc.left), ymid);
160 surface->LineTo(static_cast<int>(rc.right), ymid);