public virtual Size MeasureText(Graphics g, string text, Font font, int clipWidth, out int drawableLen)
        {
            //Logger.Debug("MeasureText clipped " + text);
            // todo: BlockRendererのMeasureVisualLines()でContract.Ensure()を満たさなくなる
            //if (Root.Canvas.UseGdiPlus) {
            //    var fmt = new StringFormat(StringFormat.GenericTypographic);
            //    var dummy = -1;
            //    var size = new SizeF(clipWidth, 20);
            //    return Size.Ceiling(g.MeasureString(text, font, size, fmt, out drawableLen, out dummy));

            //} else {
            using (var f = (Font)font.Clone())
                using (var renderer = new Gdi32TextRenderer(g, f)) {
                    //renderer.TextAlignMode = TextAlignModes.TA_LEFT | TextAlignModes.TA_TOP;
                    return(renderer.MeasureText(text, clipWidth, out drawableLen));
                }
            //}
        }
        protected virtual void DrawTextCenter(
            Graphics g, string text, Font font, Rectangle rect, Color color
            )
        {
            if (Root.Canvas.UseGdiPlus)
            {
                using (var brush = new SolidBrush(color)) {
                    var fmt = (StringFormat)StringFormat.GenericTypographic.Clone();
                    fmt.Alignment     = StringAlignment.Center;
                    fmt.LineAlignment = StringAlignment.Center;
                    fmt.FormatFlags   =
                        StringFormatFlags.NoWrap |
                        StringFormatFlags.NoClip;
                    g.DrawString(text, font, brush, rect, fmt);
                }
            }
            else
            {
                //TextRenderer.DrawText(g, text, font, rect, color, GetBulletFormatFlags());

                using (var f = (Font)font.Clone())
                    using (var renderer = new Gdi32TextRenderer(g, f)) {
                        renderer.BkMode = BkMode.TRANSPARENT;
                        //renderer.TextAlignMode = TextAlignModes.TA_CENTER | TextAlignModes.TA_TOP;
                        renderer.TextColor = color;

                        var size   = renderer.MeasureText(text);
                        var left   = rect.Left + (rect.Width - size.Width) / 2 + 1;
                        var top    = rect.Top + (rect.Height - size.Height) / 2 + 1;
                        var width  = size.Width;
                        var height = size.Height;

                        var r = new Rectangle(
                            left + Root.Canvas.AutoScrollPosition.X - Root.Left,
                            top + Root.Canvas.AutoScrollPosition.Y - Root.Top,
                            width,
                            height
                            );

                        renderer.DrawText(text, r);
                    }
            }
        }
        // --- text ---
        public virtual Size MeasureText(Graphics g, string text, Font font, int proposedWidth)
        {
            if (Root != null && Root.Canvas.UseGdiPlus)
            {
                /// Feedbackの表示でRoot == nullのことがある

                var fmt = new StringFormat(StringFormat.GenericTypographic);
                fmt.FormatFlags =
                    StringFormatFlags.NoWrap |
                    StringFormatFlags.NoClip;
                return(Size.Ceiling(g.MeasureString(text, font, proposedWidth, fmt)));
            }
            else
            {
                using (var f = (Font)font.Clone())
                    using (var renderer = new Gdi32TextRenderer(g, f)) {
                        //renderer.TextAlignMode = TextAlignModes.TA_LEFT | TextAlignModes.TA_TOP;
                        return(renderer.MeasureText(text));
                    }
            }
        }