ShippingLabels.vb
'' 
'' このコードは、DioDocs for PDF のサンプルの一部として提供されています。
'' Copyright (c) GrapeCity inc. All rights reserved.
'' 
imports System.IO
imports System.Drawing
imports System.Collections.Generic
imports GrapeCity.Documents.Drawing
imports GrapeCity.Documents.Pdf
imports GrapeCity.Documents.Text
imports GrapeCity.Documents.Barcode
imports GcWebCommon

'' このサンプルは、いくつかのバーコードを含む出荷ラベルのセットを印刷します。
'' タブストップを使用してデータを垂直に整列させることにも注意してください。
Public Class ShippingLabels
    '' Client info. This sample prints one shipping label for each client.
    Private Class Client
        Public Property Name As String
        Public Property Addr As String
        Public Property City As String
        Public Property Country As String
        Sub New(ByVal name_ As String, ByVal addr_ As String, ByVal city_ As String, ByVal country_ As String)
            Name = name_
            Addr = addr_
            City = city_
            Country = country_
        End Sub
    End Class

    '' クライアントのベース。
    Shared ReadOnly s_clients As New List(Of Client) From
    {
        New Client("Simons bistro", "Vinbćltet 34", "Křbenhavn", "Denmark"),
        New Client("Richter Supermarkt", "Starenweg 5", "Genčve", "Switzerland"),
        New Client("Bon app'", "12, rue des Bouchers", "Marseille", "France"),
        New Client("Rattlesnake Canyon Grocery", "2817 Milton Dr.", "Albuquerque", "USA"),
        New Client("Lehmanns Marktstand", "Magazinweg 7", "Frankfurt a.M.", "Germany"),
        New Client("LILA-Supermercado", "Carrera 52 con Ave. Bolívar #65-98 Llano Largo", "Barquisimeto", "Venezuela"),
        New Client("Ernst Handel", "Kirchgasse 6", "Graz", "Austria"),
        New Client("Pericles Comidas clásicas", "Calle Dr. Jorge Cash 321", "México D.F.", "Mexico"),
        New Client("Drachenblut Delikatessen", "Walserweg 21", "Aachen", "Germany"),
        New Client("Queen Cozinha", "Alameda dos Canŕrios, 891", "Săo Paulo", "Brazil"),
        New Client("Tortuga Restaurante", "Avda. Azteca 123", "México D.F.", "Mexico"),
        New Client("Save-a-lot Markets", "187 Suffolk Ln.", "Boise", "USA"),
        New Client("Franchi S.p.A.", "Via Monte Bianco 34", "Torino", "Italy")
    }

    '' ラベルを描画するために使用されるコンストラクタおよび変数です。
    Const hmargin = 24.0F, vmargin = 36.0F
    Dim _labelWidth, _labelHeight As Single
    Dim _pBold, _pNorm As Pen
    Dim _fontReg, _fontBold As Font
    Dim _tfSmall, _tfSmallB, _tfLarge As TextFormat
    Dim _tsHeader, _tsFrom, _tsCodes As List(Of TabStop)
    Dim _logo As Image
    Dim _ia As ImageAlign
    Dim bcTop, bcBottom As GcBarcode

    '' メインのサンプルドライバーです。
    Function CreatePDF(ByVal stream As Stream) As Integer
        Dim doc = New GcPdfDocument()
        Init(doc)
        '' Loop over clients, print up to 4 labels per page:
        Dim i = 0
        For pg = 0 To ((s_clients.Count + 3) / 4) - 1
            Dim page = doc.NewPage()
            PrintLabel(s_clients(i), page, New RectangleF(hmargin, vmargin, _labelWidth, _labelHeight))
            i += 1
            If (i < s_clients.Count) Then
                PrintLabel(s_clients(i), page, New RectangleF(hmargin + _labelWidth, vmargin, _labelWidth, _labelHeight))
                i += 1
            End If
            If (i < s_clients.Count) Then
                PrintLabel(s_clients(i), page, New RectangleF(hmargin, vmargin + _labelHeight, _labelWidth, _labelHeight))
                i += 1
            End If
            If (i < s_clients.Count) Then
                PrintLabel(s_clients(i), page, New RectangleF(hmargin + _labelWidth, vmargin + _labelHeight, _labelWidth, _labelHeight))
                i += 1
            End If
        Next
        '' PDF ドキュメントを保存します。
        doc.Save(stream)
        Term()
        Return doc.Pages.Count
    End Function

    '' ラベルの描画に使用される変数を初期化します。
    Private Sub Init(ByVal doc As GcPdfDocument)
        _labelWidth = (doc.PageSize.Width - hmargin * 2) / 2
        _labelHeight = _labelWidth
        _pBold = New Pen(Color.Black, 2)
        _pNorm = New Pen(Color.Black, 0.5F)
        _logo = Image.FromFile(Path.Combine("Resources", "ImagesBis", "AcmeLogo-vertical-250px.png"))
        _fontReg = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeui.ttf"))
        _fontBold = Font.FromFile(Path.Combine("Resources", "Fonts", "segoeuib.ttf"))
        _tfSmall = New TextFormat() With {.Font = _fontReg, .FontSize = 8}
        _tfSmallB = New TextFormat() With {.Font = _fontBold, .FontSize = 8}
        _tfLarge = New TextFormat() With {.Font = _fontBold, .FontSize = 14}

        _ia = New ImageAlign(ImageAlignHorz.Right, ImageAlignVert.Center, True, True, True, False, False)
        _tsHeader = New List(Of TabStop) From {New TabStop(24, TabStopAlignment.Leading), New TabStop(108, TabStopAlignment.Leading)}
        _tsFrom = New List(Of TabStop) From {New TabStop(12, TabStopAlignment.Leading), New TabStop(72, TabStopAlignment.Leading)}
        _tsCodes = New List(Of TabStop) From {New TabStop(_labelWidth / 8, TabStopAlignment.Center)}

        bcTop = New GcBarcode() With {
                .TextFormat = _tfSmall,
                .CodeType = CodeType.Code_128_B,
                .HorizontalAlignment = ImageAlignHorz.Center,
                .VerticalAlignment = ImageAlignVert.Center
            }
        bcTop.Options.CaptionPosition = BarCodeCaptionPosition.Below
        bcBottom = New GcBarcode() With {
            .TextFormat = _tfSmall,
            .CodeType = CodeType.Code_128auto,
            .HorizontalAlignment = ImageAlignHorz.Center,
            .VerticalAlignment = ImageAlignVert.Center
        }
        bcBottom.Options.CaptionPosition = BarCodeCaptionPosition.Below
    End Sub

    Private Sub Term()
        _logo.Dispose()
    End Sub

    Private Sub PrintLabel(ByVal client As Client, ByVal page As Page, ByVal bounds As RectangleF)
        '' いくつかのサンプルデータをランダム化するために使用します。
        Dim rnd = Util.NewRandom()

        '' サンプルの荷送人/送付先データです。
        Dim shipper = If(rnd.Next(2) = 0, "United Package", "Speedy Express")

        Dim sender = New With {
            .name = "ACME Inc.", .addr = "1 Main Street", .city = "Metropolis", .country = "USA", .zip = "34567"
        }

        Dim shuttle = rnd.Next(10000, 15000).ToString()

        Dim area = rnd.Next(1, 12).ToString()
        Dim tour = rnd.Next(0, 20).ToString()

        Dim g = page.Graphics

        Dim tl = g.CreateTextLayout()
        tl.DefaultFormat.Font = _tfSmall.Font
        tl.DefaultFormat.FontSize = _tfSmall.FontSize
        tl.LineSpacingScaleFactor = 0.75F
        tl.ParagraphAlignment = ParagraphAlignment.Center

        '' ヘッダー。
        Dim hHeader = bounds.Height / 2 / 5
        Dim rHeader = New RectangleF(bounds.X, bounds.Y, bounds.Width, hHeader)
        tl.TabStops = _tsHeader
        tl.Append($"{vbTab}{shipper}")
        tl.Append($"{vbTab}CMR", _tfSmallB)
        tl.Append($"{vbLf}{vbTab}{vbTab}{DateTime.Now.ToShortDateString()}")
        tl.MaxHeight = rHeader.Height
        tl.MaxWidth = rHeader.Width
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, rHeader.Location)

        Dim rLogo = rHeader
        rLogo.Inflate(-5, -5)
        g.DrawImage(_logo, rLogo, Nothing, _ia)

        '' 差出人。
        Dim hFrom = hHeader
        Dim rFrom = New RectangleF(bounds.X, rHeader.Bottom, bounds.Width, hFrom)
        tl.Clear()
        tl.TabStops = _tsFrom
        tl.Append($"{vbTab}From:{vbTab}{sender.name}{vbLf}{vbTab}{vbTab}{sender.addr}{vbLf}{vbTab}{vbTab}{sender.city}, {sender.country} {sender.zip}")
        tl.MaxHeight = rFrom.Height
        tl.MaxWidth = rFrom.Width
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, rFrom.Location)

        '' 宛先。
        Dim hTo = bounds.Height / 2 / 3
        Dim rTo = New RectangleF(bounds.X, rFrom.Bottom, bounds.Width, hTo)
        tl.Clear()
        tl.TabStops = _tsFrom
        tl.Append($"{vbTab}To:{vbTab}{client.Name}{vbLf}{vbTab}{vbTab}{client.Addr}{vbLf}{vbTab}{vbTab}{client.City}{vbLf}{vbTab}{vbTab}{client.Country}")
        tl.MaxHeight = rTo.Height
        tl.MaxWidth = rTo.Width
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, rTo.Location)

        '' コード。
        Dim hCodes = bounds.Height / 2 / (15.0F / 4)
        Dim rCodes = New RectangleF(bounds.X, rTo.Bottom, bounds.Width, hCodes)
        tl.TabStops = _tsCodes
        tl.Clear()
        tl.AppendLine($"{vbTab}Shuttle")
        tl.Append($"{vbTab}{shuttle}", _tfLarge)
        tl.MaxHeight = rCodes.Height
        tl.MaxWidth = rCodes.Width / 4
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, rCodes.Location)

        tl.Clear()
        tl.AppendLine($"{vbTab}Area")
        tl.Append($"{vbTab}{area}", _tfLarge)
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, New PointF(rCodes.X + rCodes.Width / 4, rCodes.Y))

        tl.Clear()
        tl.AppendLine($"{vbTab}Exception")
        tl.Append($"{vbTab} ", _tfLarge)
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, New PointF(rCodes.X + rCodes.Width / 4 * 2, rCodes.Y))

        tl.Clear()
        tl.AppendLine($"{vbTab}Tour")
        tl.Append($"{vbTab}{tour}", _tfLarge)
        tl.PerformLayout(True)
        g.DrawTextLayout(tl, New PointF(rCodes.X + rCodes.Width / 4 * 3, rCodes.Y))

        '' バーコード。
        Dim hBarcodes = bounds.Height / 2
        Dim rBcTop = New RectangleF(bounds.X, rCodes.Bottom, bounds.Width, hBarcodes / 2)
        Dim rBcBottom = New RectangleF(bounds.X, rBcTop.Bottom, bounds.Width, hBarcodes / 2)

        bcTop.Text = client.Country
        g.DrawBarcode(bcTop, rBcTop)

        '' 長めの「コード」を作成します。
        Dim code = $"{client.Name(0)}{client.Addr(0)}{client.City(0)}{client.Country(0)}".ToUpper()
        bcBottom.Text = $"{code}{client.GetHashCode().ToString("X12")}"
        g.DrawBarcode(bcBottom, rBcBottom)

        '' 線。
        g.DrawLine(rHeader.Left, rHeader.Bottom, rHeader.Right, rHeader.Bottom, _pNorm)
        g.DrawLine(rFrom.Left, rFrom.Bottom, rFrom.Right, rFrom.Bottom, _pNorm)
        g.DrawLine(rTo.Left, rTo.Bottom, rTo.Right, rTo.Bottom, _pNorm)
        g.DrawLine(rCodes.Left, rCodes.Bottom, rCodes.Right, rCodes.Bottom, _pNorm)

        g.DrawLine(rCodes.Left + rCodes.Width / 4, rCodes.Top, rCodes.Left + rCodes.Width / 4, rCodes.Bottom, _pNorm)
        g.DrawLine(rCodes.Left + rCodes.Width / 4 * 2, rCodes.Top, rCodes.Left + rCodes.Width / 4 * 2, rCodes.Bottom, _pNorm)
        g.DrawLine(rCodes.Left + rCodes.Width / 4 * 3, rCodes.Top, rCodes.Left + rCodes.Width / 4 * 3, rCodes.Bottom, _pNorm)

        g.DrawRectangle(bounds, _pBold)
    End Sub
End Class