xref: /MusicPlayer2/scintilla/src/LineMarker.cxx (revision 8af74909132ed5e696cb05b6689ae4baf14c1c96)
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