1*8af74909SZhong Yang // Scintilla source code edit control
2*8af74909SZhong Yang /** @file LineMarker.cxx
3*8af74909SZhong Yang ** Defines the look of a line marker in the margin.
4*8af74909SZhong Yang **/
5*8af74909SZhong Yang // Copyright 1998-2011 by Neil Hodgson <[email protected]>
6*8af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
7*8af74909SZhong Yang
8*8af74909SZhong Yang #include <cstring>
9*8af74909SZhong Yang #include <cmath>
10*8af74909SZhong Yang
11*8af74909SZhong Yang #include <stdexcept>
12*8af74909SZhong Yang #include <string>
13*8af74909SZhong Yang #include <string_view>
14*8af74909SZhong Yang #include <vector>
15*8af74909SZhong Yang #include <map>
16*8af74909SZhong Yang #include <algorithm>
17*8af74909SZhong Yang #include <memory>
18*8af74909SZhong Yang
19*8af74909SZhong Yang #include "Platform.h"
20*8af74909SZhong Yang
21*8af74909SZhong Yang #include "Scintilla.h"
22*8af74909SZhong Yang
23*8af74909SZhong Yang #include "IntegerRectangle.h"
24*8af74909SZhong Yang #include "XPM.h"
25*8af74909SZhong Yang #include "LineMarker.h"
26*8af74909SZhong Yang
27*8af74909SZhong Yang using namespace Scintilla;
28*8af74909SZhong Yang
LineMarker(const LineMarker & other)29*8af74909SZhong Yang LineMarker::LineMarker(const LineMarker &other) {
30*8af74909SZhong Yang // Defined to avoid pxpm and image being blindly copied, not as a complete copy constructor.
31*8af74909SZhong Yang markType = other.markType;
32*8af74909SZhong Yang fore = other.fore;
33*8af74909SZhong Yang back = other.back;
34*8af74909SZhong Yang backSelected = other.backSelected;
35*8af74909SZhong Yang alpha = other.alpha;
36*8af74909SZhong Yang if (other.pxpm)
37*8af74909SZhong Yang pxpm = std::make_unique<XPM>(*other.pxpm);
38*8af74909SZhong Yang else
39*8af74909SZhong Yang pxpm = nullptr;
40*8af74909SZhong Yang if (other.image)
41*8af74909SZhong Yang image = std::make_unique<RGBAImage>(*other.image);
42*8af74909SZhong Yang else
43*8af74909SZhong Yang image = nullptr;
44*8af74909SZhong Yang customDraw = other.customDraw;
45*8af74909SZhong Yang }
46*8af74909SZhong Yang
operator =(const LineMarker & other)47*8af74909SZhong Yang LineMarker &LineMarker::operator=(const LineMarker &other) {
48*8af74909SZhong Yang // Defined to avoid pxpm and image being blindly copied, not as a complete assignment operator.
49*8af74909SZhong Yang if (this != &other) {
50*8af74909SZhong Yang markType = other.markType;
51*8af74909SZhong Yang fore = other.fore;
52*8af74909SZhong Yang back = other.back;
53*8af74909SZhong Yang backSelected = other.backSelected;
54*8af74909SZhong Yang alpha = other.alpha;
55*8af74909SZhong Yang if (other.pxpm)
56*8af74909SZhong Yang pxpm = std::make_unique<XPM>(*other.pxpm);
57*8af74909SZhong Yang else
58*8af74909SZhong Yang pxpm = nullptr;
59*8af74909SZhong Yang if (other.image)
60*8af74909SZhong Yang image = std::make_unique<RGBAImage>(*other.image);
61*8af74909SZhong Yang else
62*8af74909SZhong Yang image = nullptr;
63*8af74909SZhong Yang customDraw = other.customDraw;
64*8af74909SZhong Yang }
65*8af74909SZhong Yang return *this;
66*8af74909SZhong Yang }
67*8af74909SZhong Yang
SetXPM(const char * textForm)68*8af74909SZhong Yang void LineMarker::SetXPM(const char *textForm) {
69*8af74909SZhong Yang pxpm = std::make_unique<XPM>(textForm);
70*8af74909SZhong Yang markType = SC_MARK_PIXMAP;
71*8af74909SZhong Yang }
72*8af74909SZhong Yang
SetXPM(const char * const * linesForm)73*8af74909SZhong Yang void LineMarker::SetXPM(const char *const *linesForm) {
74*8af74909SZhong Yang pxpm = std::make_unique<XPM>(linesForm);
75*8af74909SZhong Yang markType = SC_MARK_PIXMAP;
76*8af74909SZhong Yang }
77*8af74909SZhong Yang
SetRGBAImage(Point sizeRGBAImage,float scale,const unsigned char * pixelsRGBAImage)78*8af74909SZhong Yang void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) {
79*8af74909SZhong Yang image = std::make_unique<RGBAImage>(static_cast<int>(sizeRGBAImage.x), static_cast<int>(sizeRGBAImage.y), scale, pixelsRGBAImage);
80*8af74909SZhong Yang markType = SC_MARK_RGBAIMAGE;
81*8af74909SZhong Yang }
82*8af74909SZhong Yang
DrawBox(Surface * surface,int centreX,int centreY,int armSize,ColourDesired fore,ColourDesired back)83*8af74909SZhong Yang static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
84*8af74909SZhong Yang const PRectangle rc = PRectangle::FromInts(
85*8af74909SZhong Yang centreX - armSize,
86*8af74909SZhong Yang centreY - armSize,
87*8af74909SZhong Yang centreX + armSize + 1,
88*8af74909SZhong Yang centreY + armSize + 1);
89*8af74909SZhong Yang surface->RectangleDraw(rc, back, fore);
90*8af74909SZhong Yang }
91*8af74909SZhong Yang
DrawCircle(Surface * surface,int centreX,int centreY,int armSize,ColourDesired fore,ColourDesired back)92*8af74909SZhong Yang static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
93*8af74909SZhong Yang const PRectangle rcCircle = PRectangle::FromInts(
94*8af74909SZhong Yang centreX - armSize,
95*8af74909SZhong Yang centreY - armSize,
96*8af74909SZhong Yang centreX + armSize + 1,
97*8af74909SZhong Yang centreY + armSize + 1);
98*8af74909SZhong Yang surface->Ellipse(rcCircle, back, fore);
99*8af74909SZhong Yang }
100*8af74909SZhong Yang
DrawPlus(Surface * surface,int centreX,int centreY,int armSize,ColourDesired fore)101*8af74909SZhong Yang static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
102*8af74909SZhong Yang const PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
103*8af74909SZhong Yang surface->FillRectangle(rcV, fore);
104*8af74909SZhong Yang const PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
105*8af74909SZhong Yang surface->FillRectangle(rcH, fore);
106*8af74909SZhong Yang }
107*8af74909SZhong Yang
DrawMinus(Surface * surface,int centreX,int centreY,int armSize,ColourDesired fore)108*8af74909SZhong Yang static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
109*8af74909SZhong Yang const PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
110*8af74909SZhong Yang surface->FillRectangle(rcH, fore);
111*8af74909SZhong Yang }
112*8af74909SZhong Yang
Draw(Surface * surface,PRectangle & rcWhole,Font & fontForCharacter,FoldPart part,int marginStyle) const113*8af74909SZhong Yang void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, FoldPart part, int marginStyle) const {
114*8af74909SZhong Yang if (customDraw) {
115*8af74909SZhong Yang customDraw(surface, rcWhole, fontForCharacter, static_cast<int>(part), marginStyle, this);
116*8af74909SZhong Yang return;
117*8af74909SZhong Yang }
118*8af74909SZhong Yang
119*8af74909SZhong Yang ColourDesired colourHead = back;
120*8af74909SZhong Yang ColourDesired colourBody = back;
121*8af74909SZhong Yang ColourDesired colourTail = back;
122*8af74909SZhong Yang
123*8af74909SZhong Yang switch (part) {
124*8af74909SZhong Yang case FoldPart::head:
125*8af74909SZhong Yang case FoldPart::headWithTail:
126*8af74909SZhong Yang colourHead = backSelected;
127*8af74909SZhong Yang colourTail = backSelected;
128*8af74909SZhong Yang break;
129*8af74909SZhong Yang case FoldPart::body:
130*8af74909SZhong Yang colourHead = backSelected;
131*8af74909SZhong Yang colourBody = backSelected;
132*8af74909SZhong Yang break;
133*8af74909SZhong Yang case FoldPart::tail:
134*8af74909SZhong Yang colourBody = backSelected;
135*8af74909SZhong Yang colourTail = backSelected;
136*8af74909SZhong Yang break;
137*8af74909SZhong Yang default:
138*8af74909SZhong Yang // FoldPart::undefined
139*8af74909SZhong Yang break;
140*8af74909SZhong Yang }
141*8af74909SZhong Yang
142*8af74909SZhong Yang if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
143*8af74909SZhong Yang pxpm->Draw(surface, rcWhole);
144*8af74909SZhong Yang return;
145*8af74909SZhong Yang }
146*8af74909SZhong Yang if ((markType == SC_MARK_RGBAIMAGE) && (image)) {
147*8af74909SZhong Yang // Make rectangle just large enough to fit image centred on centre of rcWhole
148*8af74909SZhong Yang PRectangle rcImage;
149*8af74909SZhong Yang rcImage.top = ((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2;
150*8af74909SZhong Yang rcImage.bottom = rcImage.top + image->GetScaledHeight();
151*8af74909SZhong Yang rcImage.left = ((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2;
152*8af74909SZhong Yang rcImage.right = rcImage.left + image->GetScaledWidth();
153*8af74909SZhong Yang surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels());
154*8af74909SZhong Yang return;
155*8af74909SZhong Yang }
156*8af74909SZhong Yang
157*8af74909SZhong Yang const IntegerRectangle ircWhole(rcWhole);
158*8af74909SZhong Yang // Restrict most shapes a bit
159*8af74909SZhong Yang const PRectangle rc(rcWhole.left, rcWhole.top + 1, rcWhole.right, rcWhole.bottom - 1);
160*8af74909SZhong Yang // Ensure does not go beyond edge
161*8af74909SZhong Yang const int minDim = std::min(ircWhole.Width(), ircWhole.Height() - 2) - 1;
162*8af74909SZhong Yang int centreX = (ircWhole.right + ircWhole.left) / 2;
163*8af74909SZhong Yang const int centreY = (ircWhole.bottom + ircWhole.top) / 2;
164*8af74909SZhong Yang const int dimOn2 = minDim / 2;
165*8af74909SZhong Yang const int dimOn4 = minDim / 4;
166*8af74909SZhong Yang const int blobSize = dimOn2 - 1;
167*8af74909SZhong Yang const int armSize = dimOn2 - 2;
168*8af74909SZhong Yang if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) {
169*8af74909SZhong Yang // On textual margins move marker to the left to try to avoid overlapping the text
170*8af74909SZhong Yang centreX = ircWhole.left + dimOn2 + 1;
171*8af74909SZhong Yang }
172*8af74909SZhong Yang
173*8af74909SZhong Yang switch (markType) {
174*8af74909SZhong Yang case SC_MARK_ROUNDRECT: {
175*8af74909SZhong Yang PRectangle rcRounded = rc;
176*8af74909SZhong Yang rcRounded.left = rc.left + 1;
177*8af74909SZhong Yang rcRounded.right = rc.right - 1;
178*8af74909SZhong Yang surface->RoundedRectangle(rcRounded, fore, back);
179*8af74909SZhong Yang }
180*8af74909SZhong Yang break;
181*8af74909SZhong Yang
182*8af74909SZhong Yang case SC_MARK_CIRCLE: {
183*8af74909SZhong Yang const PRectangle rcCircle = PRectangle::FromInts(
184*8af74909SZhong Yang centreX - dimOn2,
185*8af74909SZhong Yang centreY - dimOn2,
186*8af74909SZhong Yang centreX + dimOn2,
187*8af74909SZhong Yang centreY + dimOn2);
188*8af74909SZhong Yang surface->Ellipse(rcCircle, fore, back);
189*8af74909SZhong Yang }
190*8af74909SZhong Yang break;
191*8af74909SZhong Yang
192*8af74909SZhong Yang case SC_MARK_ARROW: {
193*8af74909SZhong Yang Point pts[] = {
194*8af74909SZhong Yang Point::FromInts(centreX - dimOn4, centreY - dimOn2),
195*8af74909SZhong Yang Point::FromInts(centreX - dimOn4, centreY + dimOn2),
196*8af74909SZhong Yang Point::FromInts(centreX + dimOn2 - dimOn4, centreY),
197*8af74909SZhong Yang };
198*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
199*8af74909SZhong Yang }
200*8af74909SZhong Yang break;
201*8af74909SZhong Yang
202*8af74909SZhong Yang case SC_MARK_ARROWDOWN: {
203*8af74909SZhong Yang Point pts[] = {
204*8af74909SZhong Yang Point::FromInts(centreX - dimOn2, centreY - dimOn4),
205*8af74909SZhong Yang Point::FromInts(centreX + dimOn2, centreY - dimOn4),
206*8af74909SZhong Yang Point::FromInts(centreX, centreY + dimOn2 - dimOn4),
207*8af74909SZhong Yang };
208*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
209*8af74909SZhong Yang }
210*8af74909SZhong Yang break;
211*8af74909SZhong Yang
212*8af74909SZhong Yang case SC_MARK_PLUS: {
213*8af74909SZhong Yang Point pts[] = {
214*8af74909SZhong Yang Point::FromInts(centreX - armSize, centreY - 1),
215*8af74909SZhong Yang Point::FromInts(centreX - 1, centreY - 1),
216*8af74909SZhong Yang Point::FromInts(centreX - 1, centreY - armSize),
217*8af74909SZhong Yang Point::FromInts(centreX + 1, centreY - armSize),
218*8af74909SZhong Yang Point::FromInts(centreX + 1, centreY - 1),
219*8af74909SZhong Yang Point::FromInts(centreX + armSize, centreY - 1),
220*8af74909SZhong Yang Point::FromInts(centreX + armSize, centreY + 1),
221*8af74909SZhong Yang Point::FromInts(centreX + 1, centreY + 1),
222*8af74909SZhong Yang Point::FromInts(centreX + 1, centreY + armSize),
223*8af74909SZhong Yang Point::FromInts(centreX - 1, centreY + armSize),
224*8af74909SZhong Yang Point::FromInts(centreX - 1, centreY + 1),
225*8af74909SZhong Yang Point::FromInts(centreX - armSize, centreY + 1),
226*8af74909SZhong Yang };
227*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
228*8af74909SZhong Yang }
229*8af74909SZhong Yang break;
230*8af74909SZhong Yang
231*8af74909SZhong Yang case SC_MARK_MINUS: {
232*8af74909SZhong Yang Point pts[] = {
233*8af74909SZhong Yang Point::FromInts(centreX - armSize, centreY - 1),
234*8af74909SZhong Yang Point::FromInts(centreX + armSize, centreY - 1),
235*8af74909SZhong Yang Point::FromInts(centreX + armSize, centreY + 1),
236*8af74909SZhong Yang Point::FromInts(centreX - armSize, centreY + 1),
237*8af74909SZhong Yang };
238*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
239*8af74909SZhong Yang }
240*8af74909SZhong Yang break;
241*8af74909SZhong Yang
242*8af74909SZhong Yang case SC_MARK_SMALLRECT: {
243*8af74909SZhong Yang PRectangle rcSmall;
244*8af74909SZhong Yang rcSmall.left = rc.left + 1;
245*8af74909SZhong Yang rcSmall.top = rc.top + 2;
246*8af74909SZhong Yang rcSmall.right = rc.right - 1;
247*8af74909SZhong Yang rcSmall.bottom = rc.bottom - 2;
248*8af74909SZhong Yang surface->RectangleDraw(rcSmall, fore, back);
249*8af74909SZhong Yang }
250*8af74909SZhong Yang break;
251*8af74909SZhong Yang
252*8af74909SZhong Yang case SC_MARK_EMPTY:
253*8af74909SZhong Yang case SC_MARK_BACKGROUND:
254*8af74909SZhong Yang case SC_MARK_UNDERLINE:
255*8af74909SZhong Yang case SC_MARK_AVAILABLE:
256*8af74909SZhong Yang // An invisible marker so don't draw anything
257*8af74909SZhong Yang break;
258*8af74909SZhong Yang
259*8af74909SZhong Yang case SC_MARK_VLINE: {
260*8af74909SZhong Yang surface->PenColour(colourBody);
261*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
262*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
263*8af74909SZhong Yang }
264*8af74909SZhong Yang break;
265*8af74909SZhong Yang
266*8af74909SZhong Yang case SC_MARK_LCORNER: {
267*8af74909SZhong Yang surface->PenColour(colourTail);
268*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
269*8af74909SZhong Yang surface->LineTo(centreX, centreY);
270*8af74909SZhong Yang surface->LineTo(ircWhole.right - 1, centreY);
271*8af74909SZhong Yang }
272*8af74909SZhong Yang break;
273*8af74909SZhong Yang
274*8af74909SZhong Yang case SC_MARK_TCORNER: {
275*8af74909SZhong Yang surface->PenColour(colourTail);
276*8af74909SZhong Yang surface->MoveTo(centreX, centreY);
277*8af74909SZhong Yang surface->LineTo(ircWhole.right - 1, centreY);
278*8af74909SZhong Yang
279*8af74909SZhong Yang surface->PenColour(colourBody);
280*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
281*8af74909SZhong Yang surface->LineTo(centreX, centreY + 1);
282*8af74909SZhong Yang
283*8af74909SZhong Yang surface->PenColour(colourHead);
284*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
285*8af74909SZhong Yang }
286*8af74909SZhong Yang break;
287*8af74909SZhong Yang
288*8af74909SZhong Yang case SC_MARK_LCORNERCURVE: {
289*8af74909SZhong Yang surface->PenColour(colourTail);
290*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
291*8af74909SZhong Yang surface->LineTo(centreX, centreY - 3);
292*8af74909SZhong Yang surface->LineTo(centreX + 3, centreY);
293*8af74909SZhong Yang surface->LineTo(ircWhole.right - 1, centreY);
294*8af74909SZhong Yang }
295*8af74909SZhong Yang break;
296*8af74909SZhong Yang
297*8af74909SZhong Yang case SC_MARK_TCORNERCURVE: {
298*8af74909SZhong Yang surface->PenColour(colourTail);
299*8af74909SZhong Yang surface->MoveTo(centreX, centreY - 3);
300*8af74909SZhong Yang surface->LineTo(centreX + 3, centreY);
301*8af74909SZhong Yang surface->LineTo(ircWhole.right - 1, centreY);
302*8af74909SZhong Yang
303*8af74909SZhong Yang surface->PenColour(colourBody);
304*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
305*8af74909SZhong Yang surface->LineTo(centreX, centreY - 2);
306*8af74909SZhong Yang
307*8af74909SZhong Yang surface->PenColour(colourHead);
308*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
309*8af74909SZhong Yang }
310*8af74909SZhong Yang break;
311*8af74909SZhong Yang
312*8af74909SZhong Yang case SC_MARK_BOXPLUS: {
313*8af74909SZhong Yang DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
314*8af74909SZhong Yang DrawPlus(surface, centreX, centreY, blobSize, fore);
315*8af74909SZhong Yang }
316*8af74909SZhong Yang break;
317*8af74909SZhong Yang
318*8af74909SZhong Yang case SC_MARK_BOXPLUSCONNECTED: {
319*8af74909SZhong Yang if (part == FoldPart::headWithTail)
320*8af74909SZhong Yang surface->PenColour(colourTail);
321*8af74909SZhong Yang else
322*8af74909SZhong Yang surface->PenColour(colourBody);
323*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
324*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
325*8af74909SZhong Yang
326*8af74909SZhong Yang surface->PenColour(colourBody);
327*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
328*8af74909SZhong Yang surface->LineTo(centreX, centreY - blobSize);
329*8af74909SZhong Yang
330*8af74909SZhong Yang DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
331*8af74909SZhong Yang DrawPlus(surface, centreX, centreY, blobSize, fore);
332*8af74909SZhong Yang
333*8af74909SZhong Yang if (part == FoldPart::body) {
334*8af74909SZhong Yang surface->PenColour(colourTail);
335*8af74909SZhong Yang surface->MoveTo(centreX + 1, centreY + blobSize);
336*8af74909SZhong Yang surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
337*8af74909SZhong Yang
338*8af74909SZhong Yang surface->MoveTo(centreX + blobSize, centreY + blobSize);
339*8af74909SZhong Yang surface->LineTo(centreX + blobSize, centreY - blobSize);
340*8af74909SZhong Yang
341*8af74909SZhong Yang surface->MoveTo(centreX + 1, centreY - blobSize);
342*8af74909SZhong Yang surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
343*8af74909SZhong Yang }
344*8af74909SZhong Yang }
345*8af74909SZhong Yang break;
346*8af74909SZhong Yang
347*8af74909SZhong Yang case SC_MARK_BOXMINUS: {
348*8af74909SZhong Yang DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
349*8af74909SZhong Yang DrawMinus(surface, centreX, centreY, blobSize, fore);
350*8af74909SZhong Yang
351*8af74909SZhong Yang surface->PenColour(fore);
352*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
353*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
354*8af74909SZhong Yang }
355*8af74909SZhong Yang break;
356*8af74909SZhong Yang
357*8af74909SZhong Yang case SC_MARK_BOXMINUSCONNECTED: {
358*8af74909SZhong Yang DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
359*8af74909SZhong Yang DrawMinus(surface, centreX, centreY, blobSize, fore);
360*8af74909SZhong Yang
361*8af74909SZhong Yang surface->PenColour(fore);
362*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
363*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
364*8af74909SZhong Yang
365*8af74909SZhong Yang surface->PenColour(colourBody);
366*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
367*8af74909SZhong Yang surface->LineTo(centreX, centreY - blobSize);
368*8af74909SZhong Yang
369*8af74909SZhong Yang if (part == FoldPart::body) {
370*8af74909SZhong Yang surface->PenColour(colourTail);
371*8af74909SZhong Yang surface->MoveTo(centreX + 1, centreY + blobSize);
372*8af74909SZhong Yang surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
373*8af74909SZhong Yang
374*8af74909SZhong Yang surface->MoveTo(centreX + blobSize, centreY + blobSize);
375*8af74909SZhong Yang surface->LineTo(centreX + blobSize, centreY - blobSize);
376*8af74909SZhong Yang
377*8af74909SZhong Yang surface->MoveTo(centreX + 1, centreY - blobSize);
378*8af74909SZhong Yang surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
379*8af74909SZhong Yang }
380*8af74909SZhong Yang }
381*8af74909SZhong Yang break;
382*8af74909SZhong Yang
383*8af74909SZhong Yang case SC_MARK_CIRCLEPLUS: {
384*8af74909SZhong Yang DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
385*8af74909SZhong Yang DrawPlus(surface, centreX, centreY, blobSize, colourTail);
386*8af74909SZhong Yang }
387*8af74909SZhong Yang break;
388*8af74909SZhong Yang
389*8af74909SZhong Yang case SC_MARK_CIRCLEPLUSCONNECTED: {
390*8af74909SZhong Yang if (part == FoldPart::headWithTail)
391*8af74909SZhong Yang surface->PenColour(colourTail);
392*8af74909SZhong Yang else
393*8af74909SZhong Yang surface->PenColour(colourBody);
394*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
395*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
396*8af74909SZhong Yang
397*8af74909SZhong Yang surface->PenColour(colourBody);
398*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
399*8af74909SZhong Yang surface->LineTo(centreX, centreY - blobSize);
400*8af74909SZhong Yang
401*8af74909SZhong Yang DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
402*8af74909SZhong Yang DrawPlus(surface, centreX, centreY, blobSize, colourTail);
403*8af74909SZhong Yang }
404*8af74909SZhong Yang break;
405*8af74909SZhong Yang
406*8af74909SZhong Yang case SC_MARK_CIRCLEMINUS: {
407*8af74909SZhong Yang surface->PenColour(colourHead);
408*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
409*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
410*8af74909SZhong Yang
411*8af74909SZhong Yang DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
412*8af74909SZhong Yang DrawMinus(surface, centreX, centreY, blobSize, colourTail);
413*8af74909SZhong Yang }
414*8af74909SZhong Yang break;
415*8af74909SZhong Yang
416*8af74909SZhong Yang case SC_MARK_CIRCLEMINUSCONNECTED: {
417*8af74909SZhong Yang surface->PenColour(colourHead);
418*8af74909SZhong Yang surface->MoveTo(centreX, centreY + blobSize);
419*8af74909SZhong Yang surface->LineTo(centreX, ircWhole.bottom);
420*8af74909SZhong Yang
421*8af74909SZhong Yang surface->PenColour(colourBody);
422*8af74909SZhong Yang surface->MoveTo(centreX, ircWhole.top);
423*8af74909SZhong Yang surface->LineTo(centreX, centreY - blobSize);
424*8af74909SZhong Yang
425*8af74909SZhong Yang DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
426*8af74909SZhong Yang DrawMinus(surface, centreX, centreY, blobSize, colourTail);
427*8af74909SZhong Yang }
428*8af74909SZhong Yang break;
429*8af74909SZhong Yang
430*8af74909SZhong Yang case SC_MARK_DOTDOTDOT: {
431*8af74909SZhong Yang XYPOSITION right = static_cast<XYPOSITION>(centreX - 6);
432*8af74909SZhong Yang for (int b = 0; b < 3; b++) {
433*8af74909SZhong Yang const PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom - 2);
434*8af74909SZhong Yang surface->FillRectangle(rcBlob, fore);
435*8af74909SZhong Yang right += 5.0f;
436*8af74909SZhong Yang }
437*8af74909SZhong Yang }
438*8af74909SZhong Yang break;
439*8af74909SZhong Yang
440*8af74909SZhong Yang case SC_MARK_ARROWS: {
441*8af74909SZhong Yang surface->PenColour(fore);
442*8af74909SZhong Yang int right = centreX - 2;
443*8af74909SZhong Yang const int armLength = dimOn2 - 1;
444*8af74909SZhong Yang for (int b = 0; b < 3; b++) {
445*8af74909SZhong Yang surface->MoveTo(right, centreY);
446*8af74909SZhong Yang surface->LineTo(right - armLength, centreY - armLength);
447*8af74909SZhong Yang surface->MoveTo(right, centreY);
448*8af74909SZhong Yang surface->LineTo(right - armLength, centreY + armLength);
449*8af74909SZhong Yang right += 4;
450*8af74909SZhong Yang }
451*8af74909SZhong Yang }
452*8af74909SZhong Yang break;
453*8af74909SZhong Yang
454*8af74909SZhong Yang case SC_MARK_SHORTARROW: {
455*8af74909SZhong Yang Point pts[] = {
456*8af74909SZhong Yang Point::FromInts(centreX, centreY + dimOn2),
457*8af74909SZhong Yang Point::FromInts(centreX + dimOn2, centreY),
458*8af74909SZhong Yang Point::FromInts(centreX, centreY - dimOn2),
459*8af74909SZhong Yang Point::FromInts(centreX, centreY - dimOn4),
460*8af74909SZhong Yang Point::FromInts(centreX - dimOn4, centreY - dimOn4),
461*8af74909SZhong Yang Point::FromInts(centreX - dimOn4, centreY + dimOn4),
462*8af74909SZhong Yang Point::FromInts(centreX, centreY + dimOn4),
463*8af74909SZhong Yang Point::FromInts(centreX, centreY + dimOn2),
464*8af74909SZhong Yang };
465*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
466*8af74909SZhong Yang }
467*8af74909SZhong Yang break;
468*8af74909SZhong Yang
469*8af74909SZhong Yang case SC_MARK_FULLRECT:
470*8af74909SZhong Yang surface->FillRectangle(rcWhole, back);
471*8af74909SZhong Yang break;
472*8af74909SZhong Yang
473*8af74909SZhong Yang case SC_MARK_LEFTRECT: {
474*8af74909SZhong Yang PRectangle rcLeft = rcWhole;
475*8af74909SZhong Yang rcLeft.right = rcLeft.left + 4;
476*8af74909SZhong Yang surface->FillRectangle(rcLeft, back);
477*8af74909SZhong Yang }
478*8af74909SZhong Yang break;
479*8af74909SZhong Yang
480*8af74909SZhong Yang case SC_MARK_BOOKMARK: {
481*8af74909SZhong Yang const int halfHeight = minDim / 3;
482*8af74909SZhong Yang Point pts[] = {
483*8af74909SZhong Yang Point::FromInts(ircWhole.left, centreY - halfHeight),
484*8af74909SZhong Yang Point::FromInts(ircWhole.right - 3, centreY - halfHeight),
485*8af74909SZhong Yang Point::FromInts(ircWhole.right - 3 - halfHeight, centreY),
486*8af74909SZhong Yang Point::FromInts(ircWhole.right - 3, centreY + halfHeight),
487*8af74909SZhong Yang Point::FromInts(ircWhole.left, centreY + halfHeight),
488*8af74909SZhong Yang };
489*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
490*8af74909SZhong Yang }
491*8af74909SZhong Yang break;
492*8af74909SZhong Yang
493*8af74909SZhong Yang case SC_MARK_VERTICALBOOKMARK: {
494*8af74909SZhong Yang const int halfWidth = minDim / 3;
495*8af74909SZhong Yang Point pts[] = {
496*8af74909SZhong Yang Point::FromInts(centreX - halfWidth, centreY - dimOn2),
497*8af74909SZhong Yang Point::FromInts(centreX + halfWidth, centreY - dimOn2),
498*8af74909SZhong Yang Point::FromInts(centreX + halfWidth, centreY + dimOn2),
499*8af74909SZhong Yang Point::FromInts(centreX, centreY + dimOn2 - halfWidth),
500*8af74909SZhong Yang Point::FromInts(centreX - halfWidth, centreY + dimOn2),
501*8af74909SZhong Yang };
502*8af74909SZhong Yang surface->Polygon(pts, std::size(pts), fore, back);
503*8af74909SZhong Yang }
504*8af74909SZhong Yang break;
505*8af74909SZhong Yang
506*8af74909SZhong Yang default:
507*8af74909SZhong Yang if (markType >= SC_MARK_CHARACTER) {
508*8af74909SZhong Yang std::string character(1, static_cast<char>(markType - SC_MARK_CHARACTER));
509*8af74909SZhong Yang const XYPOSITION width = surface->WidthText(fontForCharacter, character);
510*8af74909SZhong Yang PRectangle rcText = rc;
511*8af74909SZhong Yang rcText.left += (rc.Width() - width) / 2;
512*8af74909SZhong Yang rcText.right = rc.left + width;
513*8af74909SZhong Yang surface->DrawTextClipped(rcText, fontForCharacter, rcText.bottom - 2,
514*8af74909SZhong Yang character, fore, back);
515*8af74909SZhong Yang } else {
516*8af74909SZhong Yang // treat as SC_MARK_FULLRECT
517*8af74909SZhong Yang surface->FillRectangle(rcWhole, back);
518*8af74909SZhong Yang }
519*8af74909SZhong Yang break;
520*8af74909SZhong Yang }
521*8af74909SZhong Yang }
522