internal void Render(IntPtr hdc, RenderParameter param, RenderProfile prof, int y) { if (_text[0] == '\0') { return; //何も描かなくてよい } float fx = (float)param.TargetRect.Left; RectangleF rect = new RectangleF(); rect.Y = param.TargetRect.Top + y; rect.Height = prof.Pitch.Height; GWord word = _firstWord; while (word != null) { rect.X = fx /*- prof.CharGap*/; //Nativeな描画では不要? rect.Width = param.TargetRect.Right - rect.X; int ix = (int)rect.X; int iy = (int)rect.Y; TextDecoration dec = word.Decoration; //Brush brush = prof.CalcTextBrush(dec); uint forecolorref = DrawUtil.ToCOLORREF(prof.CalcTextColor(dec)); Color bkcolor = prof.CalcBackColor(dec); uint bkcolorref = DrawUtil.ToCOLORREF(bkcolor); IntPtr hfont = prof.CalcHFONT_NoUnderline(dec, word.CharGroup); Win32.SelectObject(hdc, hfont); Win32.SetTextColor(hdc, forecolorref); Win32.SetBkColor(hdc, bkcolorref); Win32.SetBkMode(hdc, bkcolor == prof.BackColor? 1 : 2); //基本背景色と一緒ならTRANSPARENT, 異なればOPAQUE IntPtr bkbrush = bkcolor == prof.BackColor? IntPtr.Zero : Win32.CreateSolidBrush(bkcolorref); int display_length = WordDisplayLength(word); if (word.Decoration == null) //装飾なし //g.DrawString(WordText(word), font, brush, rect); { DrawWord(hdc, ix, iy, word); } else { //if(dec.Bold || (!prof.UsingIdenticalFont && word.CharGroup==CharGroup.TwoBytes)) if (dec.Bold || word.CharGroup == CharGroup.TwoBytes) //同じフォント指定でも日本語が半角の2倍でない場合あり。パフォーマンス問題はクリアされつつあるので確実に1文字ずつ描画 { DrawStringByOneChar2(hdc, word, display_length, bkbrush, rect.X, iy, prof); } else { DrawWord(hdc, ix, iy, word); //いまやアホな描画エンジンの問題からは解放された! } } //Debug.WriteLine("PW="+p.Pitch.Width+",TL="+(pb.Text.Length*p.Pitch.Width)+", real="+g.MeasureString(pb.Text, p.Font).Width); if (dec.Underline) { DrawUnderline(hdc, forecolorref, ix, iy + (int)prof.Pitch.Height - 1, (int)(prof.Pitch.Width * display_length)); } fx += prof.Pitch.Width * display_length; word = word.Next; if (bkbrush != IntPtr.Zero) { Win32.DeleteObject(bkbrush); } } }
private void DrawUnderLineCaret(Graphics g, RenderParameter param, int y, int pos) { RenderProfile profile = GetRenderProfile(); PointF pt1 = new PointF(GEnv.SystemMetrics.ControlBorderWidth + profile.Pitch.Width * pos, GEnv.SystemMetrics.ControlBorderHeight + profile.Pitch.Height * (y+1) - 2); PointF pt2 = new PointF(pt1.X + profile.Pitch.Width, pt1.Y); g.DrawLine(new Pen(GEnv.Options.CaretColor==Color.Empty? profile.ForeColor : GEnv.Options.CaretColor), pt1, pt2); }
protected override sealed void OnPaint(PaintEventArgs e) { base.OnPaint(e); try { Rectangle clip = e.ClipRectangle; Graphics g = e.Graphics; if(CoversBorder(clip)) { ControlPaint.DrawBorder3D(g, 0, 0, Width, Height, Border3DStyle.Sunken); } if(!_fakeVisible) return; if(this.DesignMode || _tag==null) return; // /*if(!_thrownFlag) { _thrownFlag = true; throw new Exception("Test exception"); } */ TerminalDocument document = _tag.Document; RenderProfile profile = GetRenderProfile(); Image img = profile.GetImage(); if(img!=null) DrawBackgroundImage(g, img, profile.ImageStyle, clip); int paneheight = GetConnection().TerminalHeight; // // RenderParameter param = new RenderParameter(); bool caret = this.Focused; int caret_pos_x = 0, caret_pos_y = 0; ArrayList lines = new ArrayList(paneheight); lock(document) { CommitTransientScrollBar(); BuildTransientDocument(e, lines, ref param, ref caret, ref caret_pos_x, ref caret_pos_y); document.ResetInvalidatedRegion(); } //Rendering Core if(param.LineFrom <= document.LastLineNumber) { RenderProfile prof = GetRenderProfile(); IntPtr hdc = g.GetHdc(); IntPtr gdipgraphics = IntPtr.Zero; try { if(prof.UseClearType) { Win32.GdipCreateFromHDC(hdc, ref gdipgraphics); Win32.GdipSetTextRenderingHint(gdipgraphics, 5); //5��TextRenderingHintClearTypeGridFit } int t = param.LineFrom+param.LineCount; float y = prof.Pitch.Height * param.LineFrom; for(int i=param.LineFrom; i<t; i++) { if(i>=lines.Count) break; GLine line = (GLine)lines[i]; line.Render(hdc, param, prof, (int)y); y += prof.Pitch.Height; } } finally { if(gdipgraphics!=IntPtr.Zero) Win32.GdipDeleteGraphics(gdipgraphics); g.ReleaseHdc(hdc); } } if(caret) { if((GEnv.Options.CaretType & CaretType.StyleMask)==CaretType.Line) DrawBarCaret(g, param, caret_pos_y, caret_pos_x); else if((GEnv.Options.CaretType & CaretType.StyleMask)==CaretType.Underline) DrawUnderLineCaret(g, param, caret_pos_y, caret_pos_x); } } catch(Exception ex) { if(!_criticalErrorRaised) { //���̒��ň�x��O����������ƌJ��Ԃ��N�����Ă��܂����Ƃ��܂܂���B�Ȃ̂ŏ���̂ݕ\�����ĂƂ肠�����蔲���� _criticalErrorRaised = true; GUtil.ReportCriticalError(ex); } } }
private void BuildTransientDocument(PaintEventArgs e, ArrayList lines, ref RenderParameter param, ref bool caret, ref int caret_pos_x, ref int caret_pos_y) { if(_tag == null) return; // �y�C������鎞�� _tag �� null �ɂȂ��Ă��邱�Ƃ����� Rectangle clip = e.ClipRectangle; TerminalDocument document = _tag.Document; RenderProfile profile = GetRenderProfile(); int paneheight = GetConnection().TerminalHeight; Win32.SystemMetrics sm = GEnv.SystemMetrics; param.TargetRect = new Rectangle(sm.ControlBorderWidth+1, sm.ControlBorderHeight, this.Width - _VScrollBar.Width - sm.ControlBorderWidth + 8, //���̂W���Ȃ��l�����������A.NET�̕����T�C�Y�ۂߖ��̂��ߍs�̍ŏI�������\������Ȃ����Ƃ�����B���������邽�߂ɂ�����Ƒ��₷ this.Height - sm.ControlBorderHeight); GLine l = document.TopLine; for(int i=0; i<paneheight; i++) { lines.Add(l.Clone()); l = l.NextLine; if(l==null) break; } //�I��̈�̕`�� TextSelection selection = GEnv.TextSelection; if(selection.Owner==this && !selection.IsEmpty) { TextSelection.TextPoint from = selection.HeadPoint; TextSelection.TextPoint to = selection.TailPoint; l = document.FindLineOrNull(from._line); GLine t = document.FindLineOrNull(to._line); if(l!=null && t!=null) { //�{����l��null�ł͂����Ȃ��͂������A������������o�O���|�[�g���������̂ŔO�̂��� t = t.NextLine; int pos = from._position; //���Ƃ����[��z���ăh���b�O�����Ƃ��̑I��͈͂͑O�s���ɂȂ�̂� pos==TerminalWidth�ƂȂ�P�[�X������B do { int index = l.ID-document.TopLineNumber; if(pos>=0 && pos<GetConnection().TerminalWidth && index>=0 && index<lines.Count) { GLine r = null; if(l.ID==to._line) { if(pos!=to._position) r = ((GLine)lines[index]).InverseRange(pos, to._position); } else r = ((GLine)lines[index]).InverseRange(pos, l.CharLength); if(r!=null) { lines[l.ID-document.TopLineNumber] = r; //if(_selectionKeyProcessor!=null && _selectionKeyProcessor.CurrentLine==l) _selectionKeyProcessor.ReplaceCurrentLine(r); document.InvalidateLine(l.ID); } } pos = 0; //�Q�s�ڂ���̑I��͍s������ l = l.NextLine; } while(l!=t); } } //�L�����b�g�ʒu�̌v�Z bool blink = (GEnv.Options.CaretType & CaretType.Blink)!=CaretType.None; GLine caret_line = null; if(_selectionKeyProcessor!=null) { caret_pos_x = _selectionKeyProcessor.UICaretPos; caret_pos_y = _selectionKeyProcessor.CurrentLine.ID - document.TopLineNumber; if(caret_pos_y>=0 && caret_pos_y < GetConnection().TerminalHeight && caret_pos_y<lines.Count) caret_line = (GLine)lines[caret_pos_y]; if(_caretState==1) caret = false; //�e�L�X�g�I����[�h�ł͏�Ƀu�����N } else { caret_pos_x = document.CaretColumn; caret_pos_y = document.CurrentLineNumber - document.TopLineNumber; if(caret_pos_y>=0 && caret_pos_y < GetConnection().TerminalHeight && caret_pos_y<lines.Count) caret_line = (GLine)lines[caret_pos_y]; if(GetConnection().IsClosed) caret = false; if(blink && _caretState==1) caret = false; } int offset1 = (int)((clip.Top - GEnv.SystemMetrics.ControlBorderHeight) / profile.Pitch.Height); param.LineFrom = offset1; int offset2 = (int)((clip.Bottom - GEnv.SystemMetrics.ControlBorderHeight) / profile.Pitch.Height); if(offset2 >= GetConnection().TerminalHeight) offset2 = GetConnection().TerminalHeight-1; param.LineCount = offset2 - offset1 + 1; //Debug.WriteLine(String.Format("{0} {1} {2}", param.LineFrom, param.LineCount, caret_pos_y)); //Caret��ʊO�ɂ���Ȃ珈���͂��Ȃ��Ă悢�B�Q�Ԗڂ̏���́AAttach-ResizeTerminal�̗���̒��ł���OnPaint����s�����ꍇ��TerminalHeight>lines.Count�ɂȂ�P�[�X������̂�h�~���邽�� if(caret_line!=null) { //�q�N�q�N���̂��߁A�L�����b�g��\�����Ȃ��Ƃ��ł���̑���͏Ȃ��Ȃ� if((GEnv.Options.CaretType & CaretType.Box)!=CaretType.None) { GLine inv = caret_line.InverseCaret(caret_pos_x, caret, false); Debug.Assert(caret_pos_y>=0); lines[caret_pos_y] = inv; } } else caret = false; }
internal void Render(IntPtr hdc, RenderParameter param, RenderProfile prof, int y) { if(_text[0]=='\0') return; //����`���Ȃ��Ă悢 float fx = (float)param.TargetRect.Left; RectangleF rect = new RectangleF(); rect.Y = param.TargetRect.Top+y; rect.Height = prof.Pitch.Height; GWord word = _firstWord; while(word != null) { rect.X = fx /*- prof.CharGap*/; //Native�ȕ`��ł͕s�v�H rect.Width = param.TargetRect.Right - rect.X; int ix = (int)rect.X; int iy = (int)rect.Y; TextDecoration dec = word.Decoration; //Brush brush = prof.CalcTextBrush(dec); uint forecolorref = DrawUtil.ToCOLORREF(prof.CalcTextColor(dec)); Color bkcolor = prof.CalcBackColor(dec); uint bkcolorref = DrawUtil.ToCOLORREF(bkcolor); IntPtr hfont = prof.CalcHFONT_NoUnderline(dec, word.CharGroup); Win32.SelectObject(hdc, hfont); Win32.SetTextColor(hdc, forecolorref); Win32.SetBkColor(hdc, bkcolorref); Win32.SetBkMode(hdc, bkcolor==prof.BackColor? 1 : 2); //��{�w�i�F�ƈꏏ�Ȃ�TRANSPARENT, �قȂ��OPAQUE IntPtr bkbrush = bkcolor==prof.BackColor? IntPtr.Zero : Win32.CreateSolidBrush(bkcolorref); int display_length = WordDisplayLength(word); if(word.Decoration==null) { //�����Ȃ� //g.DrawString(WordText(word), font, brush, rect); DrawWord(hdc, ix, iy, word); } else { //if(dec.Bold || (!prof.UsingIdenticalFont && word.CharGroup==CharGroup.TwoBytes)) if(dec.Bold || word.CharGroup==CharGroup.TwoBytes) //�����t�H���g�w��ł���{�ꂪ���p�̂Q�{�łȂ��ꍇ����B�p�t�H�[�}���X���̓N���A�������̂Ŋm���ɂP�������`�� DrawStringByOneChar2(hdc, word, display_length, bkbrush, rect.X, iy, prof); else DrawWord(hdc, ix, iy, word); //���܂�A�z�ȕ`��G���W���̖�肩��͉�����ꂽ�I } //Debug.WriteLine("PW="+p.Pitch.Width+",TL="+(pb.Text.Length*p.Pitch.Width)+", real="+g.MeasureString(pb.Text, p.Font).Width); if(dec.Underline) DrawUnderline(hdc, forecolorref, ix, iy+(int)prof.Pitch.Height-1, (int)(prof.Pitch.Width * display_length)); fx += prof.Pitch.Width * display_length; word = word.Next; if(bkbrush!=IntPtr.Zero) Win32.DeleteObject(bkbrush); } }