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); } } }
internal void Render(IntPtr hdc, RenderProfile prof, Color baseBackColor, int x, int y) { if (_text.Length == 0 || _text[0] == '\0') { return; //何も描かなくてよい。これはよくあるケース } float fx0 = (float)x; float fx1 = fx0; int y1 = y; int y2 = y1 + (int)prof.Pitch.Height; float pitch = prof.Pitch.Width; int defaultBackColorArgb = baseBackColor.ToArgb(); Win32.SetBkMode(hdc, Win32.TRANSPARENT); GWord word = _firstWord; while (word != null) { TextDecoration dec = word.Decoration; IntPtr hFont = prof.CalcHFONT_NoUnderline(dec, word.CharGroup); Win32.SelectObject(hdc, hFont); uint foreColorRef = DrawUtil.ToCOLORREF(prof.CalcTextColor(dec)); Win32.SetTextColor(hdc, foreColorRef); Color bkColor = prof.CalcBackColor(dec); bool isOpaque = (bkColor.ToArgb() != defaultBackColorArgb); if (isOpaque) { uint bkColorRef = DrawUtil.ToCOLORREF(bkColor); Win32.SetBkColor(hdc, bkColorRef); } int nextOffset = GetNextOffset(word); float fx2 = fx0 + pitch * nextOffset; if (prof.CalcBold(dec) || CharGroupUtil.IsCJK(word.CharGroup)) { // It is not always true that width of a character in the CJK font is twice of a character in the ASCII font. // Characters are drawn one by one to adjust pitch. int step = CharGroupUtil.GetColumnsPerCharacter(word.CharGroup); float charPitch = pitch * step; int offset = word.Offset; float fx = fx1; if (isOpaque) { // If background fill is required, we call ExtTextOut() with ETO_OPAQUE to draw the first character. if (offset < nextOffset) { Win32.RECT rect = new Win32.RECT((int)fx1, y1, (int)fx2, y2); char ch = _text[offset]; Debug.Assert(ch != GLine.WIDECHAR_PAD); unsafe { Win32.ExtTextOut(hdc, rect.left, rect.top, Win32.ETO_OPAQUE, &rect, &ch, 1, null); } } offset += step; fx += charPitch; } for (; offset < nextOffset; offset += step) { char ch = _text[offset]; Debug.Assert(ch != GLine.WIDECHAR_PAD); unsafe { Win32.ExtTextOut(hdc, (int)fx, y1, 0, null, &ch, 1, null); } fx += charPitch; } } else { int offset = word.Offset; int displayLength = nextOffset - offset; if (isOpaque) { Win32.RECT rect = new Win32.RECT((int)fx1, y1, (int)fx2, y2); unsafe { fixed(char *p = &_text[offset]) { Win32.ExtTextOut(hdc, rect.left, rect.top, Win32.ETO_OPAQUE, &rect, p, displayLength, null); } } } else { unsafe { fixed(char *p = &_text[offset]) { Win32.ExtTextOut(hdc, (int)fx1, y1, 0, null, p, displayLength, null); } } } } if (dec.Underline) { DrawUnderline(hdc, foreColorRef, (int)fx1, y2 - 1, (int)fx2 - (int)fx1); } fx1 = fx2; word = word.Next; } }