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 | |
| parent | f566263f31075e3d36782dd3f5901466b789f763 (diff) | |
| download | scintilla-mirror-3f329e8a6b1c4735ab1cf4f43848292db8df3d3b.tar.gz | |
Two phase drawing.
| -rw-r--r-- | gtk/PlatGTK.cxx | 22 | ||||
| -rw-r--r-- | include/Platform.h | 1 | ||||
| -rw-r--r-- | include/Scintilla.h | 2 | ||||
| -rw-r--r-- | include/Scintilla.iface | 7 | ||||
| -rw-r--r-- | src/Editor.cxx | 161 | ||||
| -rw-r--r-- | src/Editor.h | 5 | 
6 files changed, 160 insertions, 38 deletions
| diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index 7088a5f7e..9724c38bb 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -601,8 +601,10 @@ public:  	void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);  	void Copy(PRectangle rc, Point from, Surface &surfaceSource); +	void DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);  	void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);  	void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); +	void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);  	void MeasureWidths(Font &font_, const char *s, int len, int *positions);  	int WidthText(Font &font_, const char *s, int len);  	int WidthChar(Font &font_, char ch); @@ -821,9 +823,8 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {  #define MAX_US_LEN 5000 -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, -                                 ColourAllocated fore, ColourAllocated back) { -	FillRectangle(rc, back); +void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char *s, int len, +                                 ColourAllocated fore) {  	PenColour(fore);  	if (gc && drawable) {  		// Draw text as a series of segments to avoid limitations in X servers @@ -896,10 +897,23 @@ void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const ch  	}  } +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, +                                 ColourAllocated fore, ColourAllocated back) { +	FillRectangle(rc, back); +	DrawTextBase(rc, font_, ybase, s, len, fore); +} +  // On GTK+, exactly same as DrawTextNoClip  void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len,                                    ColourAllocated fore, ColourAllocated back) { -	DrawTextNoClip(rc, font_, ybase, s, len, fore, back); +	FillRectangle(rc, back); +	DrawTextBase(rc, font_, ybase, s, len, fore); +} + +// On GTK+, exactly same as DrawTextNoClip +void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, +                                  ColourAllocated fore) { +	DrawTextBase(rc, font_, ybase, s, len, fore);  }  void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positions) { diff --git a/include/Platform.h b/include/Platform.h index b19cdce8d..bb429729e 100644 --- a/include/Platform.h +++ b/include/Platform.h @@ -314,6 +314,7 @@ public:  	virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0;  	virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; +	virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0;  	virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0;  	virtual int WidthText(Font &font_, const char *s, int len)=0;  	virtual int WidthChar(Font &font_, char ch)=0; diff --git a/include/Scintilla.h b/include/Scintilla.h index 8df32be4c..386271bbe 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -395,6 +395,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,  #define SCI_SETVSCROLLBAR 2280  #define SCI_GETVSCROLLBAR 2281  #define SCI_APPENDTEXT 2282 +#define SCI_GETTWOPHASEDRAW 2283 +#define SCI_SETTWOPHASEDRAW 2284  #define SCI_LINEDOWN 2300  #define SCI_LINEDOWNEXTEND 2301  #define SCI_LINEUP 2302 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index bade44fd2..dd4d2d37e 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -1022,6 +1022,13 @@ get bool GetVScrollBar=2281(,)  # Append a string to the end of the document without changing the selection.  fun void AppendText=2282(int length, string text) +# Is drawing done in two phases with backgrounds drawn before faoregrounds? +get bool GetTwoPhaseDraw=2283(,) + +# 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. +set void SetTwoPhaseDraw=2284(bool twoPhase,) +  ## New messages go here  ## Start of key messages 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); | 
