diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/EditView.cxx | 340 | ||||
| -rw-r--r-- | src/EditView.h | 41 | ||||
| -rw-r--r-- | src/Editor.cxx | 26 | ||||
| -rw-r--r-- | src/Editor.h | 2 | ||||
| -rw-r--r-- | src/MarginView.cxx | 92 | ||||
| -rw-r--r-- | src/MarginView.h | 6 | ||||
| -rw-r--r-- | src/ViewStyle.cxx | 6 | ||||
| -rw-r--r-- | src/ViewStyle.h | 1 | 
8 files changed, 308 insertions, 206 deletions
| diff --git a/src/EditView.cxx b/src/EditView.cxx index 52bd8d332..f6fe59c1c 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -61,13 +61,117 @@ PrintParameters::PrintParameters() {  	wrapState = eWrapWord;  } +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { +	if (st.multipleStyles) { +		for (size_t iStyle = 0; iStyle<st.length; iStyle++) { +			if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) +				return false; +		} +	} else { +		if (!vs.ValidStyle(styleOffset + st.style)) +			return false; +	} +	return true; +} + +static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, +	const char *text, const unsigned char *styles, size_t len) { +	int width = 0; +	size_t start = 0; +	while (start < len) { +		size_t style = styles[start]; +		size_t endSegment = start; +		while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style)) +			endSegment++; +		FontAlias fontText = vs.styles[style + styleOffset].font; +		width += static_cast<int>(surface->WidthText(fontText, text + start, +			static_cast<int>(endSegment - start + 1))); +		start = endSegment + 1; +	} +	return width; +} + +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { +	int widthMax = 0; +	size_t start = 0; +	while (start < st.length) { +		size_t lenLine = st.LineLength(start); +		int widthSubLine; +		if (st.multipleStyles) { +			widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); +		} else { +			FontAlias fontText = vs.styles[styleOffset + st.style].font; +			widthSubLine = static_cast<int>(surface->WidthText(fontText, +				st.text + start, static_cast<int>(lenLine))); +		} +		if (widthSubLine > widthMax) +			widthMax = widthSubLine; +		start += lenLine + 1; +	} +	return widthMax; +} + +void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) { +	FontAlias fontText = style.font; +	surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length), +		style.fore, style.back); +} + +void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, +	const char *s, int len, DrawPhase phase) { +	FontAlias fontText = style.font; +	if (phase & drawBack) { +		if (phase & drawText) { +			// Drawing both +			surface->DrawTextNoClip(rc, fontText, ybase, s, len, +				style.fore, style.back); +		} else { +			surface->FillRectangle(rc, style.back); +		} +	} else if (phase & drawText) { +		surface->DrawTextTransparent(rc, fontText, ybase, s, len, style.fore); +	} +} + +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, +	const StyledText &st, size_t start, size_t length, DrawPhase phase) { + +	if (st.multipleStyles) { +		int x = static_cast<int>(rcText.left); +		size_t i = 0; +		while (i < length) { +			size_t end = i; +			size_t style = st.styles[i + start]; +			while (end < length - 1 && st.styles[start + end + 1] == style) +				end++; +			style += styleOffset; +			FontAlias fontText = vs.styles[style].font; +			const int width = static_cast<int>(surface->WidthText(fontText, +				st.text + start + i, static_cast<int>(end - i + 1))); +			PRectangle rcSegment = rcText; +			rcSegment.left = static_cast<XYPOSITION>(x); +			rcSegment.right = static_cast<XYPOSITION>(x + width + 1); +			DrawTextNoClipPhase(surface, rcSegment, vs.styles[style], +				rcText.top + vs.maxAscent, st.text + start + i, +				static_cast<int>(end - i + 1), phase); +			x += width; +			i = end + 1; +		} +	} else { +		const size_t style = st.style + styleOffset; +		DrawTextNoClipPhase(surface, rcText, vs.styles[style], +			rcText.top + vs.maxAscent, st.text + start, +			static_cast<int>(length), phase); +	} +} +  const XYPOSITION epsilon = 0.0001f;	// A small nudge to avoid floating point precision issues  EditView::EditView() {  	hideSelection = false;  	drawOverstrikeCaret = true;  	bufferedDraw = true; -	twoPhaseDraw = true; +	phasesDraw = phasesTwo;  	lineWidthMaxSeen = 0;  	additionalCaretsBlink = true;  	additionalCaretsVisible = true; @@ -78,6 +182,24 @@ EditView::EditView() {  	posCache.SetSize(0x400);  } +bool EditView::SetTwoPhaseDraw(bool twoPhaseDraw) { +	const PhasesDraw phasesDrawNew = twoPhaseDraw ? phasesTwo : phasesOne; +	const bool redraw = phasesDraw != phasesDrawNew; +	phasesDraw = phasesDrawNew; +	return redraw; +} + +bool EditView::SetPhasesDraw(int phases) { +	const PhasesDraw phasesDrawNew = static_cast<PhasesDraw>(phases); +	const bool redraw = phasesDraw != phasesDrawNew; +	phasesDraw = phasesDrawNew; +	return redraw; +} + +bool EditView::LinesOverlap() const { +	return phasesDraw == phasesMultiple; +} +  void EditView::DropGraphics(bool freeObjects) {  	if (freeObjects) {  		delete pixmapLine; @@ -569,9 +691,9 @@ static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired  	}  } -void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, -	const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) { -	if (!twoPhaseDraw) { +static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment, +	const char *s, ColourDesired textBack, ColourDesired textFore, bool fillBackground) { +	if (fillBackground) {  		surface->FillRectangle(rcSegment, textBack);  	}  	FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font; @@ -679,7 +801,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle  			} else {  				surface->FillRectangle(rcSegment, textBack);  			} -			DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw); +			DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, phasesDraw == phasesOne);  			if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {  				SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);  			} @@ -812,13 +934,15 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS  }  void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, -	int line, int xStart, PRectangle rcLine, int subLine) { +	int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {  	int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);  	PRectangle rcSegment = rcLine;  	int annotationLine = subLine - ll->lines;  	const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line);  	if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { -		surface->FillRectangle(rcSegment, vsDraw.styles[0].back); +		if (phase & drawBack) { +			surface->FillRectangle(rcSegment, vsDraw.styles[0].back); +		}  		rcSegment.left = static_cast<XYPOSITION>(xStart);  		if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) {  			// Only care about calculating width if tracking or need to draw box @@ -843,14 +967,14 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi  			lineInAnnotation++;  		}  		PRectangle rcText = rcSegment; -		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +		if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) {  			surface->FillRectangle(rcText,  				vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);  			rcText.left += vsDraw.spaceWidth;  		}  		DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, -			stAnnotation, start, lengthAnnotation); -		if (vsDraw.annotationVisible == ANNOTATION_BOXED) { +			stAnnotation, start, lengthAnnotation, phase); +		if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) {  			surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);  			surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));  			surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom)); @@ -1228,7 +1352,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi  	// Foreground drawing loop  	BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, -		((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs); +		(((phasesDraw == phasesOne) && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs);  	while (bfFore.More()) { @@ -1259,7 +1383,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi  			if (ts.representation) {  				if (ll->chars[i] == '\t') {  					// Tab display -					if (!twoPhaseDraw) { +					if (phasesDraw == phasesOne) {  						if (drawWhitespaceBackground &&  							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))  							textBack = vsDraw.whitespaceColours.back; @@ -1298,13 +1422,14 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi  							rcSegment.top + vsDraw.maxAscent,  							cc, 1, textBack, textFore);  					} else { -						DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw); +						DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), +							textBack, textFore, phasesDraw == phasesOne);  					}  				}  			} else {  				// Normal text display  				if (vsDraw.styles[styleMain].visible) { -					if (twoPhaseDraw) { +					if (phasesDraw != phasesOne) {  						surface->DrawTextTransparent(rcSegment, textFont,  							rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,  							i - ts.start + 1, textFore); @@ -1323,7 +1448,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi  									textFore = vsDraw.whitespaceColours.fore;  								if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {  									XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2; -									if (!twoPhaseDraw && drawWhitespaceBackground && +									if ((phasesDraw == phasesOne) && drawWhitespaceBackground &&  										(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {  										textBack = vsDraw.whitespaceColours.back;  										PRectangle rcSpace( @@ -1432,10 +1557,10 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode  }  void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, -	int line, int lineVisible, int xStart, PRectangle rcLine, int subLine) { +	int line, int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {  	if (subLine >= ll->lines) { -		DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine); +		DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, phase);  		return; // No further drawing  	} @@ -1448,41 +1573,51 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl  	const XYACCUMULATOR subLineStart = ll->positions[lineRange.start];  	if ((ll->wrapIndent != 0) && (subLine > 0)) { -		DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background); +		if (phase & drawBack) { +			DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background); +		}  		xStart += static_cast<int>(ll->wrapIndent);  	} -	if (twoPhaseDraw) { +	if ((phasesDraw != phasesOne) && (phase & drawBack)) {  		DrawBackground(surface, model, vsDraw, ll, rcLine, lineRange, posLineStart, xStart,  			subLine, background);  		DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end,  			xStart, subLine, subLineStart, background);  	} -	DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true); - -	DrawEdgeLine(surface, vsDraw, ll, rcLine, lineRange, xStart); - -	DrawMarkUnderline(surface, model, vsDraw, line, rcLine); +	if (phase & drawIndicatorsBack) { +		DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true); +		DrawEdgeLine(surface, vsDraw, ll, rcLine, lineRange, xStart); +		DrawMarkUnderline(surface, model, vsDraw, line, rcLine); +	} -	DrawForeground(surface, model, vsDraw, ll, lineVisible, rcLine, lineRange, posLineStart, xStart, -		subLine, background); +	if (phase & drawText) { +		DrawForeground(surface, model, vsDraw, ll, lineVisible, rcLine, lineRange, posLineStart, xStart, +			subLine, background); +	} -	DrawIndentGuidesOverEmpty(surface, model, vsDraw, ll, line, lineVisible, rcLine, xStart, subLine); +	if (phase & drawIndentationGuides) { +		DrawIndentGuidesOverEmpty(surface, model, vsDraw, ll, line, lineVisible, rcLine, xStart, subLine); +	} -	DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false); +	if (phase & drawIndicatorsFore) { +		DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false); +	}  	// End of the drawing of the current line -	if (!twoPhaseDraw) { +	if (phasesDraw == phasesOne) {  		DrawEOL(surface, model, vsDraw, ll, rcLine, line, lineRange.end,  			xStart, subLine, subLineStart, background);  	} -	if (!hideSelection) { +	if (!hideSelection && (phase & drawSelectionTranslucent)) {  		DrawTranslucentSelection(surface, model, vsDraw, ll, line, rcLine, subLine, lineRange, xStart);  	} -	DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine); +	if (phase & drawLineTranslucent) { +		DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine); +	}  }  static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, int line, PRectangle rcLine) { @@ -1527,21 +1662,15 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan  		surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage);  		surface->SetDBCSMode(model.pdoc->dbcsCodePage); -		Point ptOrigin = model.GetVisibleOriginInMain(); +		const Point ptOrigin = model.GetVisibleOriginInMain(); -		int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight; -		int ypos = 0; -		if (!bufferedDraw) -			ypos += screenLinePaintFirst * vsDraw.lineHeight; -		int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x); - -		int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; -		int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; +		const int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight; +		const int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);  		SelectionPosition posCaret = model.sel.RangeMain().caret;  		if (model.posDrag.IsValid())  			posCaret = model.posDrag; -		int lineCaret = model.pdoc->LineFromPosition(posCaret.Position()); +		const int lineCaret = model.pdoc->LineFromPosition(posCaret.Position());  		PRectangle rcTextArea = rcClient;  		if (vsDraw.marginInside) { @@ -1570,75 +1699,94 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan  		int lineDocPrevious = -1;	// Used to avoid laying out one document line multiple times  		AutoLineLayout ll(llc, 0); -		while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { - -			const int lineDoc = model.cs.DocFromDisplay(visibleLine); -			// Only visible lines should be handled by the code within the loop -			PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); -			const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); -			const int subLine = visibleLine - lineStartSet; - -			// Copy this line and its styles from the document into local arrays -			// and determine the x position at which each character starts. -			//ElapsedTime et; -			if (lineDoc != lineDocPrevious) { -				ll.Set(0); -				ll.Set(RetrieveLineLayout(lineDoc, model)); -				LayoutLine(model, lineDoc, surface, vsDraw, ll, model.wrapWidth); -				lineDocPrevious = lineDoc; +		std::vector<DrawPhase> phases; +		if (phasesDraw == phasesMultiple) { +			for (DrawPhase phase = drawBack; phase <= drawCarets; phase = static_cast<DrawPhase>(phase * 2)) { +				phases.push_back(phase);  			} -			//durLayout += et.Duration(true); +		} else { +			phases.push_back(drawAll); +		} +		for (std::vector<DrawPhase>::iterator it = phases.begin(); it != phases.end(); ++it) { +			int ypos = 0; +			if (!bufferedDraw) +				ypos += screenLinePaintFirst * vsDraw.lineHeight; +			int yposScreen = screenLinePaintFirst * vsDraw.lineHeight; +			int visibleLine = model.TopLineOfMain() + screenLinePaintFirst; +			while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) { + +				const int lineDoc = model.cs.DocFromDisplay(visibleLine); +				// Only visible lines should be handled by the code within the loop +				PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); +				const int lineStartSet = model.cs.DisplayFromDoc(lineDoc); +				const int subLine = visibleLine - lineStartSet; + +				// Copy this line and its styles from the document into local arrays +				// and determine the x position at which each character starts. +				//ElapsedTime et; +				if (lineDoc != lineDocPrevious) { +					ll.Set(0); +					ll.Set(RetrieveLineLayout(lineDoc, model)); +					LayoutLine(model, lineDoc, surface, vsDraw, ll, model.wrapWidth); +					lineDocPrevious = lineDoc; +				} +				//durLayout += et.Duration(true); -			if (ll) { -				ll->containsCaret = !hideSelection && (lineDoc == lineCaret); -				ll->hotspot = model.GetHotSpotRange(); +				if (ll) { +					ll->containsCaret = !hideSelection && (lineDoc == lineCaret); +					ll->hotspot = model.GetHotSpotRange(); -				PRectangle rcLine = rcTextArea; -				rcLine.top = static_cast<XYPOSITION>(ypos); -				rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight); +					PRectangle rcLine = rcTextArea; +					rcLine.top = static_cast<XYPOSITION>(ypos); +					rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight); -				Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); +					Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1)); -				// Highlight the current braces if any -				ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle), -					static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); +					// Highlight the current braces if any +					ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle), +						static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle); -				if (leftTextOverlap && bufferedDraw) { -					PRectangle rcSpacer = rcLine; -					rcSpacer.right = rcSpacer.left; -					rcSpacer.left -= 1; -					surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); -				} +					if (leftTextOverlap && bufferedDraw) { +						PRectangle rcSpacer = rcLine; +						rcSpacer.right = rcSpacer.left; +						rcSpacer.left -= 1; +						surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back); +					} + +					DrawLine(surface, model, vsDraw, ll, lineDoc, visibleLine, xStart, rcLine, subLine, *it); +					//durPaint += et.Duration(true); -				DrawLine(surface, model, vsDraw, ll, lineDoc, visibleLine, xStart, rcLine, subLine); -				//durPaint += et.Duration(true); +					// Restore the previous styles for the brace highlights in case layout is in cache. +					ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); -				// Restore the previous styles for the brace highlights in case layout is in cache. -				ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle); +					if (*it & drawFoldLines) { +						DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine); +					} -				DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine); +					if (*it & drawCarets) { +						DrawCarets(surface, model, vsDraw, ll, lineDoc, xStart, rcLine, subLine); +					} -				DrawCarets(surface, model, vsDraw, ll, lineDoc, xStart, rcLine, subLine); +					if (bufferedDraw) { +						Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); +						PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, +							static_cast<int>(rcClient.right - vsDraw.rightMarginWidth), +							yposScreen + vsDraw.lineHeight); +						surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); +					} -				if (bufferedDraw) { -					Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0); -					PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen, -						static_cast<int>(rcClient.right - vsDraw.rightMarginWidth), -						yposScreen + vsDraw.lineHeight); -					surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); +					lineWidthMaxSeen = Platform::Maximum( +						lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine])); +					//durCopy += et.Duration(true);  				} -				lineWidthMaxSeen = Platform::Maximum( -					lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine])); -				//durCopy += et.Duration(true); -			} +				if (!bufferedDraw) { +					ypos += vsDraw.lineHeight; +				} -			if (!bufferedDraw) { -				ypos += vsDraw.lineHeight; +				yposScreen += vsDraw.lineHeight; +				visibleLine++;  			} - -			yposScreen += vsDraw.lineHeight; -			visibleLine++;  		}  		ll.Set(0);  		//if (durPaint < 0.00000001) @@ -1843,7 +1991,7 @@ long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface,  					if (draw) {  						rcLine.top = static_cast<XYPOSITION>(ypos);  						rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight); -						DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl); +						DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl, drawAll);  					}  					ypos += vsPrint.lineHeight;  				} diff --git a/src/EditView.h b/src/EditView.h index f7705458b..2775dac59 100644 --- a/src/EditView.h +++ b/src/EditView.h @@ -20,6 +20,29 @@ struct PrintParameters {  };  /** +* The view may be drawn in separate phases. +*/ +enum DrawPhase { +	drawBack = 0x1, +	drawIndicatorsBack = 0x2, +	drawText = 0x4, +	drawIndentationGuides = 0x8, +	drawIndicatorsFore = 0x10, +	drawSelectionTranslucent = 0x20, +	drawLineTranslucent = 0x40, +	drawFoldLines = 0x80, +	drawCarets = 0x100, +	drawAll = 0x1FF, +}; + +bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st); +int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st); +void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase, +	const char *s, int len, DrawPhase phase); +void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, +	const StyledText &st, size_t start, size_t length, DrawPhase phase); + +/**  * EditView draws the main text area.  */  class EditView { @@ -32,9 +55,13 @@ public:  	/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to  	* the screen. This avoids flashing but is about 30% slower. */  	bool bufferedDraw; -	/** In twoPhaseDraw mode, drawing is performed in two phases, first the background -	* and then the foreground. This avoids chopping off characters that overlap the next run. */ -	bool twoPhaseDraw; +	/** In phasesTwo mode, drawing is performed in two phases, first the background +	* and then the foreground. This avoids chopping off characters that overlap the next run. +	* In multiPhaseDraw mode, drawing is performed in multiple phases with each phase drawing +	* one feature over the whole drawing area, instead of within one line. This allows text to +	* overlap from one line to the next. */ +	enum PhasesDraw { phasesOne, phasesTwo, phasesMultiple }; +	PhasesDraw phasesDraw;  	int lineWidthMaxSeen; @@ -50,6 +77,10 @@ public:  	EditView(); +	bool SetTwoPhaseDraw(bool twoPhaseDraw); +	bool SetPhasesDraw(int phases); +	bool LinesOverlap() const; +  	void DropGraphics(bool freeObjects);  	void AllocateGraphics(const ViewStyle &vsDraw);  	void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw); @@ -70,7 +101,7 @@ public:  		int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,  		ColourOptional background);  	void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, -		int line, int xStart, PRectangle rcLine, int subLine); +		int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);  	void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line,  		int xStart, PRectangle rcLine, int subLine) const;  	void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine, @@ -82,7 +113,7 @@ public:  	void DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,  		int line, int lineVisible, PRectangle rcLine, int xStart, int subLine);  	void DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, int line,  -		int lineVisible, int xStart, PRectangle rcLine, int subLine); +		int lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);  	void PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, PRectangle rcClient,  		const ViewStyle &vsDraw);  	long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure, diff --git a/src/Editor.cxx b/src/Editor.cxx index f716fdac0..3206c1912 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -484,7 +484,7 @@ void Editor::RedrawSelMargin(int line, bool allAfter) {  			PRectangle rcSelMargin = GetClientRectangle();  			rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;  			if (line != -1) { -				PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line))); +				PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0);  				// Inflate line rectangle if there are image markers with height larger than line height  				if (vs.largestMarkerHeight > vs.lineHeight) { @@ -514,25 +514,25 @@ void Editor::RedrawSelMargin(int line, bool allAfter) {  	}  } -PRectangle Editor::RectangleFromRange(Range r) { +PRectangle Editor::RectangleFromRange(Range r, int overlap) {  	const int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(r.First()));  	const int maxLine = cs.DisplayLastFromDoc(pdoc->LineFromPosition(r.Last()));  	const PRectangle rcClientDrawing = GetClientDrawingRectangle();  	PRectangle rc;  	const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;  	rc.left = static_cast<XYPOSITION>(vs.textStart - leftTextOverlap); -	rc.top = static_cast<XYPOSITION>((minLine - TopLineOfMain()) * vs.lineHeight); +	rc.top = static_cast<XYPOSITION>((minLine - TopLineOfMain()) * vs.lineHeight - overlap);  	if (rc.top < rcClientDrawing.top)  		rc.top = rcClientDrawing.top;  	// Extend to right of prepared area if any to prevent artifacts from caret line highlight  	rc.right = rcClientDrawing.right; -	rc.bottom = static_cast<XYPOSITION>((maxLine - TopLineOfMain() + 1) * vs.lineHeight); +	rc.bottom = static_cast<XYPOSITION>((maxLine - TopLineOfMain() + 1) * vs.lineHeight + overlap);  	return rc;  }  void Editor::InvalidateRange(int start, int end) { -	RedrawRect(RectangleFromRange(Range(start, end))); +	RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0));  }  int Editor::CurrentPosition() const { @@ -4723,7 +4723,7 @@ void Editor::CheckForChangeOutsidePaint(Range r) {  		if (!r.Valid())  			return; -		PRectangle rcRange = RectangleFromRange(r); +		PRectangle rcRange = RectangleFromRange(r, 0);  		PRectangle rcText = GetTextRectangle();  		if (rcRange.top < rcText.top) {  			rcRange.top = rcText.top; @@ -5944,11 +5944,19 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  		return view.bufferedDraw;  	case SCI_GETTWOPHASEDRAW: -		return view.twoPhaseDraw; +		return view.phasesDraw == EditView::phasesTwo;  	case SCI_SETTWOPHASEDRAW: -		view.twoPhaseDraw = wParam != 0; -		InvalidateStyleRedraw(); +		if (view.SetTwoPhaseDraw(wParam != 0)) +			InvalidateStyleRedraw(); +		break; + +	case SCI_GETPHASESDRAW: +		return view.phasesDraw; + +	case SCI_SETPHASESDRAW: +		if (view.SetPhasesDraw(static_cast<int>(wParam))) +			InvalidateStyleRedraw();  		break;  	case SCI_SETFONTQUALITY: diff --git a/src/Editor.h b/src/Editor.h index d80292a0a..be89bfd3a 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -299,7 +299,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	virtual void DiscardOverdraw();  	virtual void Redraw();  	void RedrawSelMargin(int line=-1, bool allAfter=false); -	PRectangle RectangleFromRange(Range r); +	PRectangle RectangleFromRange(Range r, int overlap);  	void InvalidateRange(int start, int end);  	bool UserVirtualSpace() const { diff --git a/src/MarginView.cxx b/src/MarginView.cxx index eabd144ab..9297eb4a8 100644 --- a/src/MarginView.cxx +++ b/src/MarginView.cxx @@ -54,92 +54,6 @@ using namespace Scintilla;  namespace Scintilla {  #endif -bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) { -	if (st.multipleStyles) { -		for (size_t iStyle = 0; iStyle<st.length; iStyle++) { -			if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) -				return false; -		} -	} else { -		if (!vs.ValidStyle(styleOffset + st.style)) -			return false; -	} -	return true; -} - -static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, -	const char *text, const unsigned char *styles, size_t len) { -	int width = 0; -	size_t start = 0; -	while (start < len) { -		size_t style = styles[start]; -		size_t endSegment = start; -		while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style)) -			endSegment++; -		FontAlias fontText = vs.styles[style + styleOffset].font; -		width += static_cast<int>(surface->WidthText(fontText, text + start, -			static_cast<int>(endSegment - start + 1))); -		start = endSegment + 1; -	} -	return width; -} - -int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) { -	int widthMax = 0; -	size_t start = 0; -	while (start < st.length) { -		size_t lenLine = st.LineLength(start); -		int widthSubLine; -		if (st.multipleStyles) { -			widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); -		} else { -			FontAlias fontText = vs.styles[styleOffset + st.style].font; -			widthSubLine = static_cast<int>(surface->WidthText(fontText, -				st.text + start, static_cast<int>(lenLine))); -		} -		if (widthSubLine > widthMax) -			widthMax = widthSubLine; -		start += lenLine + 1; -	} -	return widthMax; -} - -static void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) { -	FontAlias fontText = style.font; -	surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length), -		style.fore, style.back); -} - -void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, -	const StyledText &st, size_t start, size_t length) { - -	if (st.multipleStyles) { -		int x = static_cast<int>(rcText.left); -		size_t i = 0; -		while (i < length) { -			size_t end = i; -			size_t style = st.styles[i + start]; -			while (end < length - 1 && st.styles[start + end + 1] == style) -				end++; -			style += styleOffset; -			FontAlias fontText = vs.styles[style].font; -			const int width = static_cast<int>(surface->WidthText(fontText, -				st.text + start + i, static_cast<int>(end - i + 1))); -			PRectangle rcSegment = rcText; -			rcSegment.left = static_cast<XYPOSITION>(x); -			rcSegment.right = static_cast<XYPOSITION>(x + width + 1); -			DrawTextInStyle(surface, rcSegment, vs.styles[style], rcText.top + vs.maxAscent, -				st.text + start + i, end - i + 1); -			x += width; -			i = end + 1; -		} -	} else { -		const size_t style = st.style + styleOffset; -		DrawTextInStyle(surface, rcText, vs.styles[style], rcText.top + vs.maxAscent, -			st.text + start, length); -	} -} -  void DrawWrapMarker(Surface *surface, PRectangle rcPlace,  	bool isEndMarker, ColourDesired wrapColour) {  	surface->PenColour(wrapColour); @@ -473,8 +387,8 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect  						XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast<int>(strlen(number)));  						XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;  						rcNumber.left = xpos; -						DrawTextInStyle(surface, rcNumber, vs.styles[STYLE_LINENUMBER], -							rcNumber.top + vs.maxAscent, number, strlen(number)); +						DrawTextNoClipPhase(surface, rcNumber, vs.styles[STYLE_LINENUMBER], +							rcNumber.top + vs.maxAscent, number, static_cast<int>(strlen(number)), drawAll);  					} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {  						PRectangle rcWrapMarker = rcMarker;  						rcWrapMarker.right -= 3; @@ -492,7 +406,7 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect  								rcMarker.left = rcMarker.right - width - 3;  							}  							DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, -								stMargin, 0, stMargin.length); +								stMargin, 0, stMargin.length, drawAll);  						}  					}  				} diff --git a/src/MarginView.h b/src/MarginView.h index 8c401ae4a..465095f29 100644 --- a/src/MarginView.h +++ b/src/MarginView.h @@ -12,12 +12,6 @@  namespace Scintilla {  #endif -bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st); - -void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText, -	const StyledText &st, size_t start, size_t length); -int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st); -  void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);  /** diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx index e67c02d6d..e3c1d65d7 100644 --- a/src/ViewStyle.cxx +++ b/src/ViewStyle.cxx @@ -204,6 +204,7 @@ void ViewStyle::Init(size_t stylesSize_) {  	technology = SC_TECHNOLOGY_DEFAULT;  	lineHeight = 1; +	lineOverlap = 0;  	maxAscent = 1;  	maxDescent = 1;  	aveCharWidth = 8; @@ -329,6 +330,11 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) {  	maxAscent += extraAscent;  	maxDescent += extraDescent;  	lineHeight = maxAscent + maxDescent; +	lineOverlap = lineHeight / 10; +	if (lineOverlap < 2) +		lineOverlap = 2; +	if (lineOverlap > lineHeight) +		lineOverlap = lineHeight;  	someStylesProtected = false;  	someStylesForceCase = false; diff --git a/src/ViewStyle.h b/src/ViewStyle.h index b37387d7b..4a4ffcdf0 100644 --- a/src/ViewStyle.h +++ b/src/ViewStyle.h @@ -85,6 +85,7 @@ public:  	Indicator indicators[INDIC_MAX + 1];  	int technology;  	int lineHeight; +	int lineOverlap;  	unsigned int maxAscent;  	unsigned int maxDescent;  	XYPOSITION aveCharWidth; | 
