GoodsReturnForm.vb
'' 完毕:
Imports System.IO
Imports System.Drawing
Imports GrapeCity.Documents.Common
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Pdf
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Pdf.Annotations
Imports GrapeCity.Documents.Pdf.AcroForms
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing

'' 创建“退货或换货表格”AcroForm
'' 具有多个输入字段和复杂的布局。
Public Class GoodsReturnForm
    '' 页边距:
    Const MarginLeft = 32.0F
    Const MarginTop = 32.0F
    Const MarginRight = 32.0F
    Const MarginBottom = 32.0F
    ''
    Const TableCaptionHeight = 20.0F
    ReadOnly TableSampleHeight As Single = Textbox.Height
    Const SmallTextVOff As Single = -0.5F
    '' 部分分隔线:
    Dim CaptionLineThickness As Single = 2.5F
    '' 保存文本样式的结构:
    Private Structure TextStyle
        Public Property Font As GCTEXT.Font
        Public Property FontSize As Single
        Public Property ForeColor As Color
        Public Property GlyphAdvanceFactor As Single
    End Structure
    '' 整个表格中使用的各种样式:
    Shared TsTitle As TextStyle = New TextStyle() With {
            .Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "SitkaB.ttc")),
            .FontSize = 30,
            .ForeColor = Color.FromArgb(&HFF, &H3B, &H5C, &HAA),
            .GlyphAdvanceFactor = 0.93F
        }
    Shared TsCaption As TextStyle = New TextStyle() With {
        .Font = TsTitle.Font,
        .FontSize = 14,
        .ForeColor = Color.FromArgb(&HFF, &H3B, &H5C, &HAA),
        .GlyphAdvanceFactor = 0.93F
    }
    Shared TsBold As TextStyle = New TextStyle() With {
        .Font = GrapeCity.Documents.Text.Font.FromFile(Path.Combine("Resources", "Fonts", "arialbd.ttf")),
        .FontSize = 9,
        .ForeColor = Color.Black,
        .GlyphAdvanceFactor = 1
    }
    Shared TsNormal As TextStyle = New TextStyle() With {
        .Font = GrapeCity.Documents.Text.Font.FromFile(Path.Combine("Resources", "Fonts", "arial.ttf")),
        .FontSize = 8.0F,
        .ForeColor = Color.Black,
        .GlyphAdvanceFactor = 0.922F
    }
    Shared TsSmall As TextStyle = New TextStyle() With {
        .Font = TsNormal.Font,
        .FontSize = 5,
        .ForeColor = Color.FromArgb(&HF, &HF, &HF),
        .GlyphAdvanceFactor = 1.1F
    }
    '' 输入字段样式:
    Private Structure Textbox
        Public Shared Property Font As GCTEXT.Font = TsNormal.Font
        Public Shared Property FontSize As Single = 12
        Public Shared Property Height As Single
        Public Shared Property BaselineOffset As Single
        Public Shared Property LabelSpacing As Single = 2
    End Structure
    Private Structure Checkbox
        Public Shared Font As GCTEXT.Font = TsNormal.Font
        Public Shared FontSize As Single = TsNormal.FontSize - 2
        Public Shared Height As Single
        Public Shared BaselineOffset As Single
        Public Shared LabelSpacing As Single = 3
    End Structure
    '' 正在创建的文档:
    Private _doc As GcPdfDocument
    '' 插入点:
    Private _ip As PointF = New PointF(MarginLeft, MarginTop)
    '' 如果非空,DrawText 使用它来将文本与最后一条基线对齐:
    Private _lastBaselineOffset As Single? = Nothing
    '' 当前值的快捷方式:
    Private ReadOnly Property CurrPageIdx As Integer
        Get
            Return _doc.Pages.Count - 1
        End Get
    End Property
    Private ReadOnly Property CurrPage As Page
        Get
            Return _doc.Pages(CurrPageIdx)
        End Get
    End Property

    Private ReadOnly Property CurrGraphics As GcGraphics
        Get
            Return CurrPage.Graphics
        End Get
    End Property
    '' 静态演员:
    Shared Sub New()
        '' 初始化文本框:
        Dim tl = New TextLayout(72)
        tl.Append("Qwerty")
        tl.DefaultFormat.Font = Textbox.Font
        tl.DefaultFormat.FontSize = Textbox.FontSize
        tl.PerformLayout(True)
        Textbox.Height = tl.ContentHeight
        Textbox.BaselineOffset = tl.Lines(0).GlyphRuns(0).BaselineOffset
        '' 初始化复选框:
        tl.Clear()
        tl.Append("Qwerty")
        tl.DefaultFormat.Font = Checkbox.Font
        tl.DefaultFormat.FontSize = Checkbox.FontSize
        tl.PerformLayout(True)
        Checkbox.Height = tl.ContentHeight
        Checkbox.BaselineOffset = tl.Lines(0).GlyphRuns(0).BaselineOffset
    End Sub
    '' 主要入口点:
    Function CreatePDF(ByVal stream As Stream) As Integer
        Acme()
        _doc.Save(stream)
        Return _doc.Pages.Count
    End Function
    '' 垂直设置或前进插入点:
    Private Sub SetY(ByVal abs As Single?, ByVal offset As Single?)
        If (abs.HasValue) Then
            _ip.Y = abs.Value
        End If
        If (offset.HasValue) Then
            _ip.Y += offset.Value
        End If
        _lastBaselineOffset = Nothing
    End Sub
    '' 创建 PDF 表单:
    Private Sub Acme()
        _doc = New GcPdfDocument()
        _doc.NewPage()
        Dim pageWidth = CurrPage.Size.Width

        '' 主要标题:
        SetY(Nothing, -2)
        Dim cr = DrawText("ACME Inc.", TsTitle)
        SetY(Nothing, _lastBaselineOffset - CaptionLineThickness / 2)
        DrawGreenLine(MarginLeft, cr.Left - CaptionLineThickness)
        DrawGreenLine(cr.Right + CaptionLineThickness, pageWidth - MarginRight)

        '' ‘退换货表格’:
        SetY(cr.Bottom, 10)
        cr = DrawText("Return and Exchange Form", TsCaption)

        SetY(Nothing, CaptionLineThickness + 14)
        cr = DrawText("Please type in the appropriate information below, then print this form.", TsBold)
        _ip.X = pageWidth - 150
        cr = DrawText("Have Any Questions?", TsBold)

        SetY(Nothing, 10)
        _ip.X = MarginLeft
        cr = DrawText("(Or you may print the form and complete it by hand.)", TsNormal)
        _ip.X = pageWidth - 150
        cr = DrawText("Please call us at 800-123-4567.", TsNormal)

        '' 第 1 步 - 第 1 行:
        SetY(Nothing, 18)
        _ip.X = MarginLeft
        cr = DrawText("Step 1", TsCaption)
        _ip.X = cr.Right + 10
        cr = DrawText("Original Order #", TsBold)
        _ip.X = cr.Right + 4
        cr = DrawText("(if available):", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(120)
        _ip.X = cr.Right + 6
        cr = DrawText("Estimated Order Date:", TsBold)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        SetY(Nothing, 17)
        DrawGreenLine()
        '' 第 1 步 - 第 2 行:
        SetY(Nothing, 10)
        _ip.X = MarginLeft
        cr = DrawText("Originally Purchased by:", TsBold)
        _ip.X = cr.Right + 20
        cr = DrawCheckbox("Address Change")
        Dim col1right = pageWidth / 2 - 10
        Dim col2left = col1right + 20
        _ip.X = col2left
        cr = DrawText("Send Refund or Exchange to:", TsBold)
        _ip.X = cr.Right + 2
        cr = DrawText("(If different from left)", TsNormal)
        '' 第 1 步 - 第 3 行:
        SetY(cr.Bottom, 10)
        _ip.X = MarginLeft
        cr = DrawText("Name:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(col1right - _ip.X)
        _ip.X = col2left
        cr = DrawText("Name:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 第 1 步 - 第 4 行:
        SetY(cr.Bottom, 4 + 4)
        _ip.X = MarginLeft
        cr = DrawText("Address:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(col1right - _ip.X)
        _ip.X = col2left
        cr = DrawText("Address:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 第 1 步 - 第 5 行:
        SetY(cr.Bottom, 4 + 0.5F)
        _ip.X = MarginLeft
        cr = DrawTextbox(col1right - _ip.X)
        _ip.X = col2left
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 第 1 步 - 第 6 行(城市、州邮政编码):
        SetY(cr.Bottom, 4 + 0.5F)
        _ip.X = MarginLeft
        cr = DrawTextbox(160)
        _ip.X = cr.Right + 4
        Dim oState = _ip.X - MarginLeft
        cr = DrawTextbox(40)
        _ip.X = cr.Right + 4
        Dim oZip = _ip.X - MarginLeft
        cr = DrawTextbox(col1right - _ip.X)
        ''
        _ip.X = col2left
        cr = DrawTextbox(160)
        _ip.X = cr.Right + 4
        cr = DrawTextbox(40)
        _ip.X = cr.Right + 4
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 小文字
        SetY(cr.Bottom, SmallTextVOff)
        _ip.X = MarginLeft
        cr = DrawText("(City)", TsSmall)
        _ip.X = MarginLeft + oState
        cr = DrawText("(State)", TsSmall)
        _ip.X = MarginLeft + oZip
        cr = DrawText("(Zip)", TsSmall)
        ''
        _ip.X = col2left
        cr = DrawText("(City)", TsSmall)
        _ip.X = col2left + oState
        cr = DrawText("(State)", TsSmall)
        _ip.X = col2left + oZip
        cr = DrawText("(Zip)", TsSmall)
        '' 第 1 步 - 第 7 行(白天):
        SetY(cr.Bottom, 4 - 0.5F)
        _ip.X = MarginLeft
        cr = DrawText("Phone: (", TsNormal)
        _ip.X = cr.Right
        cr = DrawTextbox(30)
        _ip.X = cr.Right
        cr = DrawText(")", TsNormal)
        _ip.X += 3
        cr = DrawTextbox(80)
        Dim oDay = cr.Left - MarginLeft + 10
        '' (晚上)
        _ip.X = cr.Right + 3
        cr = DrawText("(", TsNormal)
        _ip.X = cr.Right
        cr = DrawTextbox(30)
        _ip.X = cr.Right
        cr = DrawText(")", TsNormal)
        _ip.X += 3
        cr = DrawTextbox(col1right - _ip.X)
        Dim oEve = cr.Left - MarginLeft + 10
        '' 
        _ip.X = col2left
        cr = DrawText("Phone: (", TsNormal)
        _ip.X = cr.Right
        cr = DrawTextbox(30)
        _ip.X = cr.Right
        cr = DrawText(")", TsNormal)
        _ip.X += 3
        cr = DrawTextbox(80)
        '' (晚上)
        _ip.X = cr.Right + 3
        cr = DrawText("(", TsNormal)
        _ip.X = cr.Right
        cr = DrawTextbox(30)
        _ip.X = cr.Right
        cr = DrawText(")", TsNormal)
        _ip.X += 3
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 小文字
        SetY(cr.Bottom, SmallTextVOff)
        _ip.X = MarginLeft + oDay
        cr = DrawText("(Daytime)", TsSmall)
        _ip.X = MarginLeft + oEve
        cr = DrawText("(Evening)", TsSmall)
        _ip.X = col2left + oDay
        cr = DrawText("(Daytime)", TsSmall)
        _ip.X = col2left + oEve
        cr = DrawText("(Evening)", TsSmall)
        '' 第 1 步 - 电子邮件
        SetY(cr.Bottom, 4 - 0.5F)
        _ip.X = MarginLeft
        cr = DrawText("Email Address:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(col1right - _ip.X)
        _ip.X = col2left
        cr = DrawText("Email Address:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 选项:
        SetY(Nothing, 16)
        _ip.X = MarginLeft
        cr = DrawText("Please select one of the following options:", TsBold)
        SetY(cr.Bottom, 2)
        cr = DrawCheckbox("Exchange for another item(s).")
        SetY(cr.Bottom, 2)
        cr = DrawCheckbox("Send me an ACME Gift Card for the amount of the refund.")
        SetY(cr.Bottom, 2)
        cr = DrawCheckbox("Reimburse my original method of payment. " +
            "(Gift recipients who select this option will receive a merchandise only gift card.)")

        '' 第2步:
        SetY(Nothing, 18)
        _ip.X = MarginLeft
        cr = DrawText("Step 2–Returns", TsCaption)
        _ip.X = cr.Right + 10
        cr = DrawText("In the form below please indicate the item(s) you are returning, " +
            "including a reason code.", TsNormal)
        SetY(Nothing, 17)
        DrawGreenLine()
        SetY(Nothing, 10)
        cr = DrawReturnsTable()
        SetY(cr.Bottom, 10)
        cr = DrawReasonCodes()

        '' 步骤3:
        SetY(Nothing, 25)
        _ip.X = MarginLeft
        cr = DrawText("Step 3–Exchanges", TsCaption)
        _ip.X = cr.Right + 10
        SetY(Nothing, -5)
        cr = DrawText(
            "For the fastest service, call Customer Service at 800-123-4567 to request a QuickExchange " +
            "or place a new order online or by phone. We'll ship your new item right away. " +
            "Note: If you use our QuickExchange option, you do not need to fill out Step 3.",
            TsNormal)
        SetY(Nothing, 22)
        DrawGreenLine()

        SetY(Nothing, 10)
        cr = DrawExchangesTable()

        '' 步骤4:
        SetY(Nothing, 18)
        _ip.X = MarginLeft
        cr = DrawText("Step 4", TsCaption)
        SetY(Nothing, 17)
        DrawGreenLine()

        SetY(Nothing, 10)
        _ip.X = MarginLeft
        Dim oCc = col2left - 30
        cr = DrawText("Method of Payment:", TsBold)
        _ip.X = oCc
        cr = DrawText("Credit Card Information:", TsBold)
        SetY(cr.Bottom, 2)
        _ip.X = MarginLeft
        cr = DrawText("If the total of your exchange or new order exceeds the value of your" + vbCrLf +
            "return, please provide a method of payment. (Select one)", TsNormal)
        _ip.X = oCc
        cr = DrawCheckbox("ACME® Visa®")
        Dim oCcOff = 90
        _ip.X += oCcOff
        cr = DrawCheckbox("MasterCard®")
        _ip.X += oCcOff
        cr = DrawCheckbox("JCB Card™")

        SetY(cr.Bottom, 2)
        _ip.X = oCc
        cr = DrawCheckbox("VISA")
        _ip.X += oCcOff
        cr = DrawCheckbox("American Express")
        _ip.X += oCcOff
        cr = DrawCheckbox("Discover®/Novus® Cards")

        SetY(cr.Bottom, 4)
        _ip.X = MarginLeft
        cr = DrawCheckbox("Credit Card")
        SetY(cr.Bottom, 2)
        cr = DrawCheckbox("Check or Money Order enclosed")
        SetY(cr.Bottom, 2)
        cr = DrawCheckbox("Gift Card, Gift Certificate or ACME Visa coupon dollars." + vbCrLf +
            "Enter # below (for Gift Cards, please include PIN).")
        _ip.X = oCc
        cr = DrawText("Card Number:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(180)
        _ip.X = cr.Right + 4
        cr = DrawTextbox(pageWidth - MarginRight - _ip.X)
        '' 小文字
        SetY(cr.Bottom, SmallTextVOff)
        _ip.X = cr.Left
        cr = DrawText("Exp. Date (MM/YY)", TsSmall)

        SetY(cr.Bottom, 10)
        _ip.X = MarginLeft
        cr = DrawText("Number:", TsNormal)
        _ip.X = cr.Right + Textbox.LabelSpacing
        cr = DrawTextbox(140)
        Dim tbBottom = cr.Bottom
        _ip.X = cr.Right + 4
        cr = DrawTextbox(60)
        Dim oPin = cr.Left
        _ip.X = oCc
        cr = DrawText("Signature:", TsNormal)
        CurrGraphics.DrawLine(New PointF(cr.Right, cr.Bottom),
            New PointF(pageWidth - MarginRight, cr.Bottom), Color.Black, 0.5F)
        '' 小文字
        SetY(tbBottom, SmallTextVOff)
        _ip.X = oPin
        cr = DrawText("PIN", TsSmall)
    End Sub

    Private Sub DrawGreenLine(Optional ByVal from_ As Single? = Nothing, Optional ByVal to_ As Single? = Nothing)
        Dim page = CurrPage
        If Not from_.HasValue Then
            from_ = MarginLeft
        End If
        If Not to_.HasValue Then
            to_ = page.Size.Width - MarginRight
        End If
        Dim g = page.Graphics
        Dim pen = New GCDRAW.Pen(TsTitle.ForeColor, CaptionLineThickness)
        g.DrawLine(New PointF(from_.Value, _ip.Y), New PointF(to_.Value, _ip.Y), pen)
    End Sub

    Private Function DrawText(ByVal text As String, ByVal ts As TextStyle) As RectangleF
        Dim page = CurrPage
        Dim tl = page.Graphics.CreateTextLayout()
        tl.MaxWidth = page.Size.Width - MarginRight - _ip.X
        If ts.FontSize = TsTitle.FontSize Then
            tl.TextAlignment = TextAlignment.Center
        End If
        tl.DefaultFormat.Font = ts.Font
        tl.DefaultFormat.FontSize = ts.FontSize
        tl.DefaultFormat.GlyphAdvanceFactor = ts.GlyphAdvanceFactor
        tl.DefaultFormat.ForeColor = ts.ForeColor
        tl.Append(text)
        tl.PerformLayout(True)
        Dim line = tl.Lines(tl.Lines.Count - 1)
        Dim run = line.GlyphRuns(0)
        Dim baselineOffset = run.BaselineOffset
        Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - baselineOffset), _ip)
        page.Graphics.DrawTextLayout(tl, p)
        If Not _lastBaselineOffset.HasValue Then
            _lastBaselineOffset = baselineOffset ''#34 within one 'line', keep imports the first offset
        End If
        Return New RectangleF(_ip.X + tl.ContentX, _ip.Y + tl.ContentY, tl.ContentWidth, tl.ContentHeight)
    End Function

    Private Function DrawTextbox(ByVal width As Single, Optional ByVal inTable As Boolean = False) As RectangleF
        Dim fld = New TextField()
        fld.Widget.Page = CurrPage
        Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - Textbox.BaselineOffset), _ip)
        fld.Widget.Rect = New RectangleF(p.X, p.Y, width, Textbox.Height)
        If inTable Then
            fld.Widget.Border = Nothing
        Else
            fld.Widget.Border.Style = BorderStyle.Underline
        End If
        fld.Widget.DefaultAppearance.Font = Textbox.Font
        fld.Widget.DefaultAppearance.FontSize = Textbox.FontSize
        _doc.AcroForm.Fields.Add(fld)
        If Not _lastBaselineOffset.HasValue Then
            _lastBaselineOffset = Textbox.BaselineOffset
        End If
        Return fld.Widget.Rect
    End Function

    Private Function DrawCheckbox(ByVal text As String) As RectangleF
        Dim fld = New CheckBoxField()
        fld.Widget.Page = CurrPage
        Dim p = If(_lastBaselineOffset.HasValue, New PointF(_ip.X, _ip.Y + _lastBaselineOffset.Value - Checkbox.BaselineOffset), _ip)
        fld.Widget.Rect = New RectangleF(p.X, p.Y, Checkbox.Height, Checkbox.Height)
        _doc.AcroForm.Fields.Add(fld)
        If Not _lastBaselineOffset.HasValue Then
            _lastBaselineOffset = Checkbox.BaselineOffset
        End If
        Dim pSave = _ip
        _ip.X = fld.Widget.Rect.Right + Checkbox.LabelSpacing
        Dim r = DrawText(Text, TsNormal)
        _ip = pSave
        Return New RectangleF(fld.Widget.Rect.X, r.Y, r.Right - fld.Widget.Rect.Left, r.Height)
    End Function

    Private Function DrawReturnsTable() As RectangleF
        Dim widths As Single() = {
            55,
            60,
            60,
            35,
            35,
            200,
            50,
            0
        }
        Dim captions As String() = {
            "Reason Code",
            "Item #",
            "Color",
            "Size",
            "Quantity",
            "Item Name",
            "Pirce",
            "Total"
        }
        Dim samples As String() = {
            "23",
            "KK123456",
            "Navy",
            "8",
            "1",
            "Example Item Only",
            "59.00",
            "59.00"
        }
        Return DrawTable(widths, captions, samples, 4)
    End Function

    Private Function DrawExchangesTable() As RectangleF
        '' 该表有两个特殊的额外标题,跨越两个专栏。
        '' 为了实现这一目标,我们:
        '' - 强制将这 4 列中的列标题打印为“第二段”,
        ''   从而为跨度标题留下一个空行;
        '' - 作为特殊情况在此处打印跨度标题。
        Dim widths As Single() = {
            50,
            25,
            25,
            25,
            25,
            60,
            150,
            50,
            40,
            25,
            35,
            0
        }
        Dim captions As String() = {
            "Item",
            "Style",
            vbCrLf + "1st",
            vbCrLf + "2nd",
            "Size",
            "Sleeve Length" + vbCrLf + "& Inseam",
            "Item Name",
            vbCrLf + "Characters",
            vbCrLf + "Style",
            "Qty.",
            "Price",
            "Total"
        }
        Dim samples As String() = {
            "LH123456",
            "Plain",
            "Tan",
            "Olive",
            "8",
            "28",
            "Example Item Only",
            "Amanda",
            "Block",
            "1",
            "49.95",
            "49.95"
        }

        Dim cr = DrawTable(widths, captions, samples, 4)

        '' 打印 2 个跨标题:
        Dim g = CurrGraphics
        Dim tl = g.CreateTextLayout()
        tl.ParagraphAlignment = ParagraphAlignment.Near
        tl.TextAlignment = TextAlignment.Center
        tl.DefaultFormat.Font = TsNormal.Font
        tl.DefaultFormat.FontSize = TsNormal.FontSize
        tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor
        tl.DefaultFormat.ForeColor = Color.White
        tl.WrapMode = WrapMode.NoWrap
        '' 颜色选择
        Dim width = widths(2) + widths(3)
        tl.MaxWidth = width
        tl.Append("Color Choice")
        tl.PerformLayout(True)
        Dim pt = New PointF(cr.Left + widths(0) + widths(1), cr.Top)
        g.DrawTextLayout(tl, pt)
        Dim pen = New GCDRAW.Pen(Color.White, 0.5F)
        Dim pt1 = New PointF(pt.X + 0.5F, pt.Y + TableCaptionHeight / 2)
        Dim pt2 = New PointF(pt1.X + width, pt1.Y)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + widths(2) + 0.5F, pt.Y + TableCaptionHeight / 2)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + 0.5F, pt.Y)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + width + 0.5F, pt.Y)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)
        '' 字母组合
        width = widths(7) + widths(8)
        tl.Inlines.Clear()
        tl.MaxWidth = width
        tl.Append("Monogramming")
        tl.PerformLayout(True)
        pt = New PointF(cr.Left + widths(0) + widths(1) + widths(2) + widths(3) + widths(4) + widths(5) + widths(6), cr.Top)
        g.DrawTextLayout(tl, pt)
        pt1 = New PointF(pt.X + 0.5F, pt.Y + TableCaptionHeight / 2)
        pt2 = New PointF(pt1.X + width, pt1.Y)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + widths(7) + 0.5F, pt.Y + TableCaptionHeight / 2)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + 0.5F, pt.Y)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)
        pt1 = New PointF(pt.X + width + 0.5F, pt.Y)
        pt2 = New PointF(pt1.X, pt.Y + TableCaptionHeight)
        g.DrawLine(pt1, pt2, pen)

        Return cr
    End Function

    Private Function DrawTable(ByVal widths As Single(), ByVal captions As String(), ByVal samples As String(), ByVal rowCount As Integer) As RectangleF
        Debug.Assert(captions.Length = widths.Length AndAlso samples.Length = widths.Length)

        Dim ipSave = _ip
        Dim p = New GCDRAW.Pen(Color.Black, 0.5F)

        Dim g = CurrGraphics
        Dim tl = g.CreateTextLayout()
        tl.ParagraphAlignment = ParagraphAlignment.Center
        tl.TextAlignment = TextAlignment.Center
        tl.DefaultFormat.Font = TsNormal.Font
        tl.DefaultFormat.FontSize = TsNormal.FontSize
        tl.DefaultFormat.GlyphAdvanceFactor = TsNormal.GlyphAdvanceFactor
        tl.DefaultFormat.ForeColor = Color.White
        tl.WrapMode = WrapMode.NoWrap
        tl.MaxHeight = TableCaptionHeight
        Dim totW = 0F
        For i = 0 To widths.Length - 1
            If i = widths.Length - 1 Then
                widths(i) = CurrPage.Size.Width - MarginLeft - MarginRight - totW - 1
                totW += 1
            End If
            totW += widths(i)
        Next
        g.FillRectangle(New RectangleF(MarginLeft, _ip.Y, totW, TableCaptionHeight), Color.Black)
        Dim pt = New PointF(MarginLeft, _ip.Y)
        For i = 0 To widths.Length - 1
            tl.MaxWidth = widths(i)
            tl.Append(captions(i))
            tl.PerformLayout(True)
            g.DrawTextLayout(tl, pt)
            pt.X = pt.X + widths(i)
            tl.Inlines.Clear()
        Next
        tl.DefaultFormat.ForeColor = Color.Teal
        tl.MaxHeight = TableSampleHeight
        pt = New PointF(MarginLeft, _ip.Y + TableCaptionHeight)
        For i = 0 To widths.Length - 1
            tl.MaxWidth = widths(i)
            tl.Append(samples(i))
            tl.PerformLayout(True)
            g.DrawTextLayout(tl, pt)
            pt.X = pt.X + widths(i)
            tl.Inlines.Clear()
        Next
        SetY(_ip.Y + TableCaptionHeight + TableSampleHeight, 0.5F)
        For row = 0 To rowCount - 1
            _ip.X = MarginLeft + 1
            For i = 0 To widths.Length - 1
                Dim cr = DrawTextbox(widths(i) - 1, True)
                _ip.X = cr.Right + 1
            Next
            g.DrawLine(New PointF(MarginLeft, _ip.Y - 0.5F), New PointF(MarginLeft + totW, _ip.Y - 0.5F), p)
            SetY(Nothing, Textbox.Height + 1)
        Next
        Dim totH = TableCaptionHeight + TableSampleHeight + (Textbox.Height + 1) * rowCount
        _ip.X = MarginLeft + 0.5F
        For i = 0 To widths.Length - 2
            _ip.X += widths(i)
            g.DrawLine(New PointF(_ip.X, ipSave.Y), New PointF(_ip.X, ipSave.Y + totH), p)
        Next

        Dim rect = New RectangleF(MarginLeft, ipSave.Y, totW, totH)
        g.DrawRectangle(rect, p)

        Return rect
    End Function

    Private Function DrawReasonCodes() As RectangleF
        Dim startX = 150.0F
        Dim capOff = 16.0F
        Dim colOff = 110.0F
        Dim ipSave = _ip

        _ip.X = startX
        Dim cr = DrawText("01", TsNormal)
        _ip.X += capOff
        cr = DrawText("Unsatisfactory", TsNormal)
        _ip.X = startX + colOff
        cr = DrawText("33", TsNormal)
        _ip.X += capOff
        cr = DrawText("Did not like color", TsNormal)
        _ip.X = startX + colOff * 2
        cr = DrawText("23", TsNormal)
        _ip.X += capOff
        cr = DrawText("Ordered wrong size", TsNormal)
        _ip.X = startX + colOff * 3
        cr = DrawText("51", TsNormal)
        _ip.X += capOff
        cr = DrawText("Shipping damage", TsNormal)
        SetY(Nothing, TsNormal.FontSize + 2)
        _ip.X = startX
        cr = DrawText("02", TsNormal)
        _ip.X += capOff
        cr = DrawText("Defective construction", TsNormal)
        _ip.X = startX + colOff
        cr = DrawText("21", TsNormal)
        _ip.X += capOff
        cr = DrawText("Too small", TsNormal)
        _ip.X = startX + colOff * 2
        cr = DrawText("25", TsNormal)
        _ip.X += capOff
        cr = DrawText("Too short", TsNormal)
        _ip.X = startX + colOff * 3
        cr = DrawText("52", TsNormal)
        _ip.X += capOff
        cr = DrawText("Wrong item shipped", TsNormal)

        _ip.X = MarginLeft + 10
        cr = DrawText("Reason Codes", TsBold)
        Dim lineX = cr.Right + 20

        SetY(Nothing, TsNormal.FontSize + 2)
        _ip.X = startX
        cr = DrawText("31", TsNormal)
        _ip.X += capOff
        cr = DrawText("Did not like styling", TsNormal)
        _ip.X = startX + colOff
        cr = DrawText("22", TsNormal)
        _ip.X += capOff
        cr = DrawText("Too large", TsNormal)
        _ip.X = startX + colOff * 2
        cr = DrawText("36", TsNormal)
        _ip.X += capOff
        cr = DrawText("Too long", TsNormal)

        Dim rect = New RectangleF(MarginLeft, ipSave.Y, CurrPage.Size.Width, cr.Bottom - ipSave.Y)
        CurrGraphics.DrawLine(lineX, rect.Top, lineX, rect.Bottom, Color.Black, 0.5F)

        Return rect
    End Function
End Class