diff options
| author | nyamatongwe <unknown> | 2003-02-02 01:41:11 +0000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2003-02-02 01:41:11 +0000 | 
| commit | 3f329e8a6b1c4735ab1cf4f43848292db8df3d3b (patch) | |
| tree | 77571d9565a2b712ea7e7efbe0df63100817fb25 /src | |
| parent | f566263f31075e3d36782dd3f5901466b789f763 (diff) | |
| download | scintilla-mirror-3f329e8a6b1c4735ab1cf4f43848292db8df3d3b.tar.gz | |
Two phase drawing.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Editor.cxx | 161 | ||||
| -rw-r--r-- | src/Editor.h | 5 | 
2 files changed, 132 insertions, 34 deletions
| diff --git a/src/Editor.cxx b/src/Editor.cxx index 8ac091e8d..0c540d513 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -297,6 +297,7 @@ Editor::Editor() {  	mouseDownCaptures = true;  	bufferedDraw = true; +	twoPhaseDraw = true;  	lastClickTime = 0;  	dwellDelay = SC_TIME_FOREVER; @@ -1764,6 +1765,34 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou  	}  } +ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground, +	ColourAllocated background, bool inSelection, int styleMain, int i, LineLayout *ll) { +	if (inSelection) { +		if (vsDraw.selbackset) { +			if (primarySelection) +				return vsDraw.selbackground.allocated; +			else +				return vsDraw.selbackground2.allocated; +		} +	} else { +		if ((vsDraw.edgeState == EDGE_BACKGROUND) && +			(i >= ll->edgeColumn) && +			(ll->chars[i] != '\n') && +			(ll->chars[i] != '\r')) +			return vsDraw.edgecolour.allocated; +		if (overrideBackground) +			return background; +	} +	return vsDraw.styles[styleMain].back.allocated; +} + +void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { +	Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0); +	PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom); +	surface->Copy(rcCopyArea, from, +		highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide); +} +  void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,                        PRectangle rcLine, LineLayout *ll, int subLine) { @@ -1810,6 +1839,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  		}  	} +	bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) && +		(!overrideBackground) && (vsDraw.whitespaceBackgroundSet); +  	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline.  	int indentWidth = pdoc->indentInChars * vsDraw.spaceWidth;  	if (indentWidth == 0) @@ -1818,7 +1850,6 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  	int posLineStart = pdoc->LineStart(line);  	int posLineEnd = pdoc->LineStart(line + 1); -	int styleMask = pdoc->stylingBitsMask;  	int startseg = ll->LineStart(subLine);  	int subLineStart = ll->positions[startseg];  	int lineStart = 0; @@ -1827,7 +1858,63 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  		lineStart = ll->LineStart(subLine);  		lineEnd = ll->LineStart(subLine+1);  	} -	for (int i = lineStart; i < lineEnd; i++) { +	int i; + +	// Background drawing loop +	for (i = lineStart; twoPhaseDraw && (i < lineEnd); i++) { + +		int iDoc = i + posLineStart; +		// If there is the end of a style run for any reason +		if ((ll->styles[i] != ll->styles[i + 1]) || +				i == (lineEnd-1) || +		        IsControlCharacter(ll->chars[i]) || IsControlCharacter(ll->chars[i + 1]) || +		        ((ll->selStart != ll->selEnd) && ((iDoc + 1 == ll->selStart) || (iDoc + 1 == ll->selEnd))) || +		        (i == (ll->edgeColumn - 1))) { +			rcSegment.left = ll->positions[startseg] + xStart - subLineStart; +			rcSegment.right = ll->positions[i + 1] + xStart - subLineStart; +			// Only try to draw if really visible - enhances performance by not calling environment to +			// draw strings that are completely past the right side of the window. +			if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { +				int styleMain = ll->styles[i]; +				bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd); +				ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, styleMain, i, ll); +				if (ll->chars[i] == '\t') { +					// Tab display +					if (drawWhitespaceBackground && +						(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) +						textBack = vsDraw.whitespaceBackground.allocated; +					surface->FillRectangle(rcSegment, textBack); +				} else if (IsControlCharacter(ll->chars[i])) { +					// Control character display +					inIndentation = false; +					surface->FillRectangle(rcSegment, textBack); +				} else { +					// Normal text display +					surface->FillRectangle(rcSegment, textBack); +					if (vsDraw.viewWhitespace != wsInvisible || +					        (inIndentation && vsDraw.viewIndentationGuides)) { +						for (int cpos = 0; cpos <= i - startseg; cpos++) { +							if (ll->chars[cpos + startseg] == ' ') { +								if (drawWhitespaceBackground && +									(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { +									PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top, +										ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom); +									surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated); +								} +							} else { +								inIndentation = false; +							} +						} +					} +				} +			} +			startseg = i + 1; +		} +	} +	inIndentation = subLine == 0;	// Do not handle indentation except on first subline. +	startseg = ll->LineStart(subLine); +	// Foreground drawing loop +	for (i = lineStart; i < lineEnd; i++) {  		int iDoc = i + posLineStart;  		// If there is the end of a style run for any reason @@ -1842,30 +1929,21 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  			// draw strings that are completely past the right side of the window.  			if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) {  				int styleMain = ll->styles[i]; -				ColourAllocated textBack = vsDraw.styles[styleMain].back.allocated;  				ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated;  				Font &textFont = vsDraw.styles[styleMain].font;  				bool inSelection = (iDoc >= ll->selStart) && (iDoc < ll->selEnd) && (ll->selStart != ll->selEnd); -				if (inSelection) { -					if (vsDraw.selbackset) { -						if (primarySelection) -							textBack = vsDraw.selbackground.allocated; -						else -							textBack = vsDraw.selbackground2.allocated; -					} -					if (vsDraw.selforeset) -						textFore = vsDraw.selforeground.allocated; -				} else { -					if (overrideBackground) -						textBack = background; -					if ((vsDraw.edgeState == EDGE_BACKGROUND) && (i >= ll->edgeColumn) && (ll->chars[i] != '\n') && (ll->chars[i] != '\r')) -						textBack = vsDraw.edgecolour.allocated; +				if (inSelection && (vsDraw.selforeset)) { +					textFore = vsDraw.selforeground.allocated;  				} +				ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, styleMain, i, ll);  				if (ll->chars[i] == '\t') { -					// Manage tab display -					if (!overrideBackground && vsDraw.whitespaceBackgroundSet && (vsDraw.viewWhitespace != wsInvisible) && (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) -						textBack = vsDraw.whitespaceBackground.allocated; -					surface->FillRectangle(rcSegment, textBack); +					// Tab display +					if (!twoPhaseDraw) { +						if (drawWhitespaceBackground && +							(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) +							textBack = vsDraw.whitespaceBackground.allocated; +						surface->FillRectangle(rcSegment, textBack); +					}  					if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) {  						if (vsDraw.whitespaceForegroundSet)  							textFore = vsDraw.whitespaceForeground.allocated; @@ -1874,10 +1952,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  					if (inIndentation && vsDraw.viewIndentationGuides) {  						for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {  							if (xIG >= ll->positions[i] && xIG > 0) { -								Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); -								PRectangle rcCopyArea(xIG + xStart + 1, rcSegment.top, xIG + xStart + 2, rcSegment.bottom); -								surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == xIG) ? -									      *pixmapIndentGuideHighlight : *pixmapIndentGuide); +								DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment, +									(ll->xHighlightGuide == xIG));  							}  						}  					} @@ -1889,12 +1965,14 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  						}  					}  				} else if (IsControlCharacter(ll->chars[i])) { -					// Manage control character display +					// Control character display  					inIndentation = false;  					if (controlCharSymbol < 32) {  						// Draw the character  						const char *ctrlChar = ControlCharacterString(ll->chars[i]); -						surface->FillRectangle(rcSegment, textBack); +						if (!twoPhaseDraw) { +							surface->FillRectangle(rcSegment, textBack); +						}  						int normalCharHeight = surface->Ascent(ctrlCharsFont) -  									   surface->InternalLeading(ctrlCharsFont);  						PRectangle rcCChar = rcSegment; @@ -1918,10 +1996,16 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  										  cc, 1, textBack, textFore);  					}  				} else { -					// Manage normal display -					surface->DrawTextNoClip(rcSegment, textFont, +					// Normal text display +					if (twoPhaseDraw) { +						surface->DrawTextTransparent(rcSegment, textFont, +					                  rcSegment.top + vsDraw.maxAscent, ll->chars + startseg, +					                  i - startseg + 1, textFore); +					} else { +						surface->DrawTextNoClip(rcSegment, textFont,  					                  rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,  					                  i - startseg + 1, textFore, textBack); +					}  					if (vsDraw.viewWhitespace != wsInvisible ||  					        (inIndentation && vsDraw.viewIndentationGuides)) {  						for (int cpos = 0; cpos <= i - startseg; cpos++) { @@ -1931,7 +2015,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  										textFore = vsDraw.whitespaceForeground.allocated;  									if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {  										int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2; -										if (!overrideBackground && vsDraw.whitespaceBackgroundSet) { +										if (!twoPhaseDraw && drawWhitespaceBackground && +											(!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {  											textBack = vsDraw.whitespaceBackground.allocated;  											PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top, ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom);  											surface->FillRectangle(rcSpace, textBack); @@ -1945,10 +2030,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  								if (inIndentation && vsDraw.viewIndentationGuides) {  									int startSpace = ll->positions[cpos + startseg];  									if (startSpace > 0 && (startSpace % indentWidth == 0)) { -										Point from(0, ((lineVisible & 1) && (vsDraw.lineHeight & 1)) ? 1 : 0); -										PRectangle rcCopyArea(startSpace + xStart + 1, rcSegment.top, startSpace + xStart + 2, rcSegment.bottom); -										surface->Copy(rcCopyArea, from, (ll->xHighlightGuide == ll->positions[cpos + startseg]) ? -										              *pixmapIndentGuideHighlight : *pixmapIndentGuide); +										DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment, +											(ll->xHighlightGuide == ll->positions[cpos + startseg]));  									}  								}  							} else { @@ -1994,6 +2077,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis  	}  	// End of the drawing of the current line +	int styleMask = pdoc->stylingBitsMask; +  	// Fill in a PRectangle representing the end of line characters  	int xEol = ll->positions[lineEnd] - subLineStart;  	rcSegment.left = xEol + xStart; @@ -5114,6 +5199,14 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	case SCI_GETBUFFEREDDRAW:  		return bufferedDraw; +	case SCI_GETTWOPHASEDRAW: +		return twoPhaseDraw; + +	case SCI_SETTWOPHASEDRAW: +		twoPhaseDraw = wParam != 0; +		InvalidateStyleRedraw(); +		break; +  	case SCI_SETTABWIDTH:  		if (wParam > 0)  			pdoc->tabInChars = wParam; diff --git a/src/Editor.h b/src/Editor.h index 5517065b6..ed5cc6612 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -199,6 +199,9 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	/** 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;  	int xOffset;		///< Horizontal scrolled amount in pixels  	int xCaretMargin;	///< Ensure this many pixels visible on both sides of caret @@ -348,6 +351,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	LineLayout *RetrieveLineLayout(int lineNumber);  	void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll,  		int width=LineLayout::wrapWidthInfinite); +	ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, bool inSelection, int styleMain, int i, LineLayout *ll); +	void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);  	void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,  		PRectangle rcLine, LineLayout *ll, int subLine=0);  	void Paint(Surface *surfaceWindow, PRectangle rcArea); | 
