''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System.Drawing
Imports System.IO
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Layout
Imports GrapeCity.Documents.Layout.Composition
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
'' This integrated demo shows how to use helper classes
'' in the GrapeCity.Documents.Layout.Composition namespace
'' to create complex and flexible constraint-based layouts
'' with custom z-order and clipping.
Public Class LayoutDemos
Private Shared ReadOnly PageColor As Color = Color.FromArgb(39, 41, 43)
Private Shared ReadOnly BoxColor As Color = Color.FromArgb(230, 230, 230)
Private Shared ReadOnly CodeColor As Color = Color.FromArgb(132, 211, 232)
Private Shared ReadOnly RectColor As Color = Color.FromArgb(64, 126, 148)
Private Shared ReadOnly DescColor As Color = Color.White
Private Delegate Sub DrawLayoutSample(g As GcGraphics, pageSize As Size)
Private Shared ReadOnly c_samples As Dictionary(Of String, DrawLayoutSample) = New Dictionary(Of String, DrawLayoutSample) From {
{"DrawSample1", AddressOf DrawSample1},
{"DrawSample2", AddressOf DrawSample2},
{"DrawSample3", AddressOf DrawSample3},
{"DrawSample4", AddressOf DrawSample4},
{"DrawSample5", AddressOf DrawSample5},
{"DrawSample6", AddressOf DrawSample6},
{"DrawSample7", AddressOf DrawSample7},
{"DrawSample8", AddressOf DrawSample8}
}
Public Function GenerateImage(
ByVal pixelSize As Size,
ByVal dpi As Single,
ByVal opaque As Boolean,
Optional ByVal sampleParams As String() = Nothing) As GcBitmap
Dim drawSample As DrawLayoutSample = Nothing
If Not c_samples.TryGetValue(sampleParams(3), drawSample) Then
Throw New Exception($"Unknown parameterized sample: {sampleParams(3)}")
End If
Dim bmp = New GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi)
Using g = bmp.CreateGraphics(PageColor)
drawSample(g, pixelSize)
End Using
Return bmp
End Function
'' Strings are name, description, info. Rest are arbitrary strings:
Public Shared Function GetSampleParamsList() As List(Of String())
Return New List(Of String()) From {
New String() {"Figures 1-4", "Figures 1-4: horizontal, vertical, alignment constraint and guidelines", Nothing, "DrawSample1"},
New String() {"Figure 5", "Figure 5: Barrier constraint anchored to two visuals", Nothing, "DrawSample2"},
New String() {"Figure 6", "Figure 6: Horizontal chain with weighted widths", Nothing, "DrawSample3"},
New String() {"Figure 7", "Figure 7: Horizontal chain with evenly distributed rectangles and margins", Nothing, "DrawSample4"},
New String() {"Figure 8", "Figure 8: Horizontal chain with evenly distributed rectangles, no margins", Nothing, "DrawSample5"},
New String() {"Figure 9", "Figure 9: Weighted horizontal chain without margins", Nothing, "DrawSample6"},
New String() {"Figure 10", "Figure 10: Horizontal chain with weighted margins and packed rectangles", Nothing, "DrawSample7"},
New String() {"Text Flow", "Text flow in and around non-rectangular contours", Nothing, "DrawSample8"}
}
End Function
'' Figures 1-4: horizontal, vertical, alignment constraint and guidelines.
Private Shared Sub DrawSample1(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(1.4F)
'' The Surface object can layout Visuals and draw them on the graphics.
Dim surf = New Surface()
'' view1
'' The View object represents a group of Visuals with a transformation matrix.
Dim view1 = surf.CreateView(250, 150).Translate(50, 40)
'' Visual is an element with the associated LayoutRect used for its
'' positioning/ and a delegate that draws its content on the graphics.
Dim v = view1.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(1, "A horizontal constraint to the parent:",
"rA.SetLeft(null, AnchorParam.Left, 90);")
v.LayoutRect.AnchorExact(Nothing)
v = view1.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetLeft(Nothing, AnchorParam.Left, 90)
rA.SetWidth(70)
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
Dim r = view1.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rA, 0, 0)
r.SetLeft(Nothing, AnchorParam.Left)
r.SetRight(rA, AnchorParam.Left)
'' view2
Dim view2 = surf.CreateView(250, 150).Translate(350, 40)
v = view2.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(2, "An offset horizontal alignment constraint:",
"rB.SetLeft(rA, AnchorParam.Left, 40);")
v.LayoutRect.AnchorExact(Nothing)
v = view2.CreateVisual(AddressOf DrawRect)
rA = v.LayoutRect
rA.AnchorTopLeft(Nothing, 15, 70, 110, 60)
v.Tag = "A"
v = view2.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetLeft(rA, AnchorParam.Left, 40)
rB.SetWidth(60)
rB.SetHeight(35)
rB.SetTop(rA, AnchorParam.Bottom, 20)
v.Tag = "B"
r = view2.CreateVisual(AddressOf DrawVertLineWithLeftArrow).LayoutRect
r.SetTop(rA, AnchorParam.VerticalCenter)
r.SetBottom(rB, AnchorParam.VerticalCenter)
r.SetLeft(rA, AnchorParam.Left)
r.SetRight(rB, AnchorParam.Left)
'' view3
Dim view3 = surf.CreateView(250, 150).Translate(50, 260)
v = view3.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(3, "Horizontal and vertical constraints:",
"rB.SetLeft(rA, AnchorParam.Right, 50);" & vbLf &
"rC.SetTop(rA, AnchorParam.Bottom, 40);")
v.LayoutRect.AnchorExact(Nothing)
v = view3.CreateVisual(AddressOf DrawRect)
rA = v.LayoutRect
rA.AnchorTopLeft(Nothing, 15, 30, 70, 40)
v.Tag = "A"
v = view3.CreateVisual(AddressOf DrawRect)
rB = v.LayoutRect
rB.SetLeft(rA, AnchorParam.Right, 50)
rB.SetWidth(70)
rB.SetHeight(40)
rB.SetTop(rA, AnchorParam.Top)
v.Tag = "B"
v = view3.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.SetTop(rA, AnchorParam.Bottom, 40)
rC.SetWidth(70)
rC.SetHeight(40)
rC.SetLeft(rA, AnchorParam.Left)
v.Tag = "C"
r = view3.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rA, 0, 0)
r.SetLeft(rA, AnchorParam.Right)
r.SetRight(rB, AnchorParam.Left)
r = view3.CreateVisual(AddressOf DrawLineWithUpArrow).LayoutRect
r.AnchorLeftRight(rA, 0, 0)
r.SetTop(rA, AnchorParam.Bottom)
r.SetBottom(rC, AnchorParam.Top)
'' view4
Dim view4 = surf.CreateView(250, 150).Translate(350, 260)
Dim layoutView = view4.LayoutView
v = view4.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(4, "A rectangle constrained to a guideline:",
"var anchorPoint = layoutView.CreatePoint(0.25f, 0);" & vbLf &
"rA.SetLeft(anchorPoint, 60);")
v.LayoutRect.AnchorExact(Nothing)
'' An anchor point can work as the guideline on the X or the Y axes.
Dim anchorPoint = layoutView.CreatePoint(0.25F, 0)
v = view4.CreateVisual(AddressOf DrawVertGuideline)
Dim rG = v.LayoutRect
rG.SetLeft(anchorPoint)
rG.AnchorVerticalLine(Nothing)
v.Tag = "25 %"
v = view4.CreateVisual(AddressOf DrawRect)
rA = v.LayoutRect
rA.SetLeft(anchorPoint, 60)
rA.SetWidth(70)
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
r = view4.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rA, 0, 0)
r.SetLeft(rG, AnchorParam.Left)
r.SetRight(rA, AnchorParam.Left)
surf.Render(g)
End Sub
'' Figure 5: Barrier constraint anchored to two visuals.
Private Shared Sub DrawSample2(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(2)
Dim surf = New Surface()
'' View1
Dim view1 = surf.CreateView(350, 160).Translate(30, 30)
view1.CreateVisual(AddressOf DrawView).LayoutRect.AnchorExact(Nothing)
Dim v = view1.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.AnchorTopLeft(Nothing, 30, 50, 60, 40)
v.Tag = "A"
v = view1.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.AnchorTopLeft(Nothing, 90, 50, 90, 40)
v.Tag = "B"
v = view1.CreateVisual(AddressOf DrawVertGuideline)
Dim rG = v.LayoutRect
'' Adding multiple MinLeft constraints to the same rectangle creates
'' a barrier to be used as the base for other rectangles.
rG.AppendMinLeft(rA, AnchorParam.Right)
rG.AppendMinLeft(rB, AnchorParam.Right)
rG.AnchorVerticalLine(Nothing)
v = view1.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.AppendMinLeft(rA, AnchorParam.Right, 50)
rC.AppendMinLeft(rB, AnchorParam.Right, 50)
rC.SetWidth(70)
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
Dim r = view1.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rC, 0, 0)
r.SetLeft(rG, AnchorParam.Right)
r.SetRight(rC, AnchorParam.Left)
'' View2
Dim view2 = surf.CreateView(350, 160).Translate(30, 210)
v = view2.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(5, "C is constrained to a barrier, which moves based on" & vbLf &
"the position and size of both A and B:",
"rC.AppendMinLeft(rA, AnchorParam.Right, 50);" & vbLf &
"rC.AppendMinLeft(rB, AnchorParam.Right, 50);")
v.LayoutRect.AnchorExact(Nothing)
v = view2.CreateVisual(AddressOf DrawRect)
rA = v.LayoutRect
rA.AnchorTopLeft(Nothing, 30, 50, 130, 40)
v.Tag = "A"
v = view2.CreateVisual(AddressOf DrawRect)
rB = v.LayoutRect
rB.AnchorTopLeft(Nothing, 90, 50, 90, 40)
v.Tag = "B"
v = view2.CreateVisual(AddressOf DrawVertGuideline)
rG = v.LayoutRect
rG.AppendMinLeft(rA, AnchorParam.Right)
rG.AppendMinLeft(rB, AnchorParam.Right)
rG.AnchorVerticalLine(Nothing)
v = view2.CreateVisual(AddressOf DrawRect)
rC = v.LayoutRect
rC.AppendMinLeft(rA, AnchorParam.Right, 50)
rC.AppendMinLeft(rB, AnchorParam.Right, 50)
rC.SetWidth(70)
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
r = view2.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rC, 0, 0)
r.SetLeft(rG, AnchorParam.Right)
r.SetRight(rC, AnchorParam.Left)
surf.Render(g)
End Sub
'' Figure 6: Horizontal chain with weighted widths.
Private Shared Sub DrawSample3(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(2)
Dim surf = New Surface()
Dim view = surf.CreateView(350, 120).Translate(30, 40)
Dim v = view.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(6, "A horizontal chain with two rectangles having weighted" & vbLf & "widths and a fixed space between them:",
"rA.SetLeft(null, AnchorParam.Left, 60);" & vbLf &
"rA.SetStarWidth(1);" & vbLf &
"rAB.SetLeftAndOpposite(rA, AnchorParam.Right);" & vbLf &
"rAB.SetWidth(50);" & vbLf &
"rB.SetLeftAndOpposite(rAB, AnchorParam.Right);" & vbLf &
"rB.SetStarWidth(2);" & vbLf &
"rB.SetRight(null, AnchorParam.Right, -60);")
v.LayoutRect.AnchorExact(Nothing)
v = view.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
v = view.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetHeight(40)
rB.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "B"
Dim rAB = view.CreateVisual(AddressOf DrawLeftRightLines).LayoutRect
rAB.AnchorTopBottom(rA, 0, 0)
'' The SetStarWidth method sets the weight of width of that specific
'' rectangle relative to the width of other rectangles that belong
'' to the same chain and have the "star" width.
'' SetLeftAndOpposite method makes a chain of rectangles that affect
'' the position of each other in both directions.
rA.SetLeft(Nothing, AnchorParam.Left, 60)
rA.SetStarWidth(1)
rAB.SetLeftAndOpposite(rA, AnchorParam.Right)
rAB.SetWidth(50)
rB.SetLeftAndOpposite(rAB, AnchorParam.Right)
rB.SetStarWidth(2)
rB.SetRight(Nothing, AnchorParam.Right, -60)
Dim r = view.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rA, 0, 0)
r.SetLeft(Nothing, AnchorParam.Left)
r.SetRight(rA, AnchorParam.Left)
r = view.CreateVisual(AddressOf DrawLineWithRightArrow).LayoutRect
r.AnchorTopBottom(rB, 0, 0)
r.SetLeft(rB, AnchorParam.Right)
r.SetRight(Nothing, AnchorParam.Right)
surf.Render(g)
End Sub
'' Figure 7: Horizontal chain with evenly distributed rectangles and margins.
Private Shared Sub DrawSample4(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(1.8F)
Dim surf = New Surface()
Dim view = surf.CreateView(430, 120).Translate(30, 40)
Dim v = view.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(7, "A horizontal chain with three evenly distributed rectangles" & vbLf & "after margins are accounted for:",
"rA.SetLeft(null, AnchorParam.Left, 60);" & vbLf &
"rA.SetWidth(70);" & vbLf &
"rAB.SetLeftAndOpposite(rA, AnchorParam.Right);" & vbLf &
"rAB.SetStarWidth(1);" & vbLf &
"rAB.SetRightAndOpposite(rB, AnchorParam.Left);" & vbLf &
"rB.SetWidth(70);" & vbLf &
"rBC.SetLeftAndOpposite(rB, AnchorParam.Right);" & vbLf &
"rBC.SetStarWidth(1);" & vbLf &
"rC.SetLeftAndOpposite(rBC, AnchorParam.Right);" & vbLf &
"rC.SetWidth(70);" & vbLf &
"rC.SetRight(null, AnchorParam.Right, -60);")
v.LayoutRect.AnchorExact(Nothing)
v = view.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
v = view.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetHeight(40)
rB.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "B"
v = view.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
Dim rAB = view.CreateVisual(AddressOf DrawLeftRightLines).LayoutRect
rAB.AnchorTopBottom(rA, 0, 0)
Dim rBC = view.CreateVisual(AddressOf DrawLeftRightLines).LayoutRect
rBC.AnchorTopBottom(rB, 0, 0)
rA.SetLeft(Nothing, AnchorParam.Left, 60)
rA.SetWidth(70)
rAB.SetLeftAndOpposite(rA, AnchorParam.Right)
rAB.SetStarWidth(1)
rAB.SetRightAndOpposite(rB, AnchorParam.Left)
rB.SetWidth(70)
rBC.SetLeftAndOpposite(rB, AnchorParam.Right)
rBC.SetStarWidth(1)
rC.SetLeftAndOpposite(rBC, AnchorParam.Right)
rC.SetWidth(70)
rC.SetRight(Nothing, AnchorParam.Right, -60)
Dim r = view.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
r.AnchorTopBottom(rA, 0, 0)
r.SetLeft(Nothing, AnchorParam.Left)
r.SetRight(rA, AnchorParam.Left)
r = view.CreateVisual(AddressOf DrawLineWithRightArrow).LayoutRect
r.AnchorTopBottom(rC, 0, 0)
r.SetLeft(rC, AnchorParam.Right)
r.SetRight(Nothing, AnchorParam.Right)
surf.Render(g)
End Sub
'' Figure 8: Horizontal chain with evenly distributed rectangles, no margins.
Private Shared Sub DrawSample5(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(2)
Dim surf = New Surface()
Dim view = surf.CreateView(340, 120).Translate(30, 40)
Dim v = view.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(8, "Same as Figure 7, without accounting for the margins:",
"rA.SetLeft(null, AnchorParam.Left);" & vbLf &
"rA.SetWidth(70);" & vbLf &
"rA.SetRightAndOpposite(rAB, AnchorParam.Left);" & vbLf &
"rAB.SetStarWidth(1);" & vbLf &
"rB.SetLeftAndOpposite(rAB, AnchorParam.Right);" & vbLf &
"rB.SetWidth(70);" & vbLf &
"rB.SetRightAndOpposite(rBC, AnchorParam.Left);" & vbLf &
"rBC.SetStarWidth(1);" & vbLf &
"rC.SetLeftAndOpposite(rBC, AnchorParam.Right);" & vbLf &
"rC.SetWidth(70);" & vbLf &
"rC.SetRight(null, AnchorParam.Right);")
v.LayoutRect.AnchorExact(Nothing)
v = view.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
v = view.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetHeight(40)
rB.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "B"
v = view.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
Dim rAB = view.CreateVisual(AddressOf DrawLeftRightLines).LayoutRect
rAB.AnchorTopBottom(rA, 0, 0)
Dim rBC = view.CreateVisual(AddressOf DrawLeftRightLines).LayoutRect
rBC.AnchorTopBottom(rB, 0, 0)
rA.SetLeft(Nothing, AnchorParam.Left)
rA.SetWidth(70)
rA.SetRightAndOpposite(rAB, AnchorParam.Left)
rAB.SetStarWidth(1)
rB.SetLeftAndOpposite(rAB, AnchorParam.Right)
rB.SetWidth(70)
rB.SetRightAndOpposite(rBC, AnchorParam.Left)
rBC.SetStarWidth(1)
rC.SetLeftAndOpposite(rBC, AnchorParam.Right)
rC.SetWidth(70)
rC.SetRight(Nothing, AnchorParam.Right)
surf.Render(g)
End Sub
'' Figure 9: Weighted horizontal chain without margins.
Private Shared Sub DrawSample6(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(2)
Dim surf = New Surface()
Dim view = surf.CreateView(340, 120).Translate(30, 40)
Dim v = view.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(9, "A weighted horizontal chain without margins:",
"rA.SetLeft(null, AnchorParam.Left);" & vbLf &
"rA.SetStarWidth(1);" & vbLf &
"rA.SetRightAndOpposite(rB, AnchorParam.Left);" & vbLf &
"rB.SetStarWidth(2);" & vbLf &
"rB.SetRightAndOpposite(rC, AnchorParam.Left);" & vbLf &
"rC.SetStarWidth(2);" & vbLf &
"rC.SetRight(null, AnchorParam.Right);")
v.LayoutRect.AnchorExact(Nothing)
v = view.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
v = view.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetHeight(40)
rB.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "B"
v = view.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
rA.SetLeft(Nothing, AnchorParam.Left)
rA.SetStarWidth(1)
rA.SetRightAndOpposite(rB, AnchorParam.Left)
rB.SetStarWidth(2)
rB.SetRightAndOpposite(rC, AnchorParam.Left)
rC.SetStarWidth(2)
rC.SetRight(Nothing, AnchorParam.Right)
surf.Render(g)
End Sub
'' Figure 10: Horizontal chain with weighted margins and packed rectangles.
Private Shared Sub DrawSample7(g As GcGraphics, pageSize As Size)
g.Transform = Matrix3x2.CreateScale(2)
Dim surf = New Surface()
Dim view = surf.CreateView(370, 120).Translate(30, 40)
Dim v = view.CreateVisual(AddressOf DrawView)
v.Tag = New FigureCaption(10, "Rectangles are packed together after margins with weights" & vbLf & "are accounted for:",
"rBeforeA.SetLeft(null, AnchorParam.Left);" & vbLf &
"rBeforeA.SetStarWidth(3);" & vbLf &
"rA.SetLeftAndOpposite(rBeforeA, AnchorParam.Right);" & vbLf &
"rA.SetWidth(70);" & vbLf &
"rB.SetLeftAndOpposite(rA, AnchorParam.Right);" & vbLf &
"rB.SetWidth(70);" & vbLf &
"rC.SetLeftAndOpposite(rB, AnchorParam.Right);" & vbLf &
"rC.SetWidth(70);" & vbLf &
"rAfterC.SetLeftAndOpposite(rC, AnchorParam.Right);" & vbLf &
"rAfterC.SetStarWidth(1);" & vbLf &
"rAfterC.SetRight(null, AnchorParam.Right);")
v.LayoutRect.AnchorExact(Nothing)
v = view.CreateVisual(AddressOf DrawRect)
Dim rA = v.LayoutRect
rA.SetHeight(40)
rA.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "A"
v = view.CreateVisual(AddressOf DrawRect)
Dim rB = v.LayoutRect
rB.SetHeight(40)
rB.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "B"
v = view.CreateVisual(AddressOf DrawRect)
Dim rC = v.LayoutRect
rC.SetHeight(40)
rC.SetVerticalCenter(Nothing, AnchorParam.VerticalCenter)
v.Tag = "C"
Dim rBeforeA = view.CreateVisual(AddressOf DrawLineWithLeftArrow).LayoutRect
rBeforeA.AnchorTopBottom(rA, 0, 0)
Dim rAfterC = view.CreateVisual(AddressOf DrawLineWithRightArrow).LayoutRect
rAfterC.AnchorTopBottom(rC, 0, 0)
rBeforeA.SetLeft(Nothing, AnchorParam.Left)
rBeforeA.SetStarWidth(3)
rA.SetLeftAndOpposite(rBeforeA, AnchorParam.Right)
rA.SetWidth(70)
rB.SetLeftAndOpposite(rA, AnchorParam.Right)
rB.SetWidth(70)
rC.SetLeftAndOpposite(rB, AnchorParam.Right)
rC.SetWidth(70)
rAfterC.SetLeftAndOpposite(rC, AnchorParam.Right)
rAfterC.SetStarWidth(1)
rAfterC.SetRight(Nothing, AnchorParam.Right)
surf.Render(g)
End Sub
'' Text flow in and around non-rectangular contours.
Private Shared Sub DrawSample8(g As GcGraphics, pageSize As Size)
g.FillRectangle(New RectangleF(0, 0, pageSize.Width, pageSize.Height), Color.White)
Dim surf = New Surface()
'' Contour objects can be referenced in constraints defined for text rectangles.
Dim c1_outer As Contour = Nothing
CreateFigure1(surf, c1_outer)
Dim c2_outer As Contour = Nothing
Dim c2_inner As Contour = Nothing
CreateFigure2(surf, c2_outer, c2_inner)
Const rowHeight As Single = 24F
Const lineSpacing As Single = 5F
Const paragraphSpacing As Single = 10F
Const fontSize As Single = 18F
'' The main View object that displays horizontal text.
Dim view = surf.CreateView(pageSize.Width, pageSize.Height)
Dim rcMargin = view.CreateSpace().LayoutRect
rcMargin.AnchorDeflate(Nothing, 20)
Dim tf = New TextFormat() With
{
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSans.ttf")),
.FontSizeInGraphicUnits = True,
.FontSize = fontSize,
.FontFeatures = New FontFeature() {New FontFeature(FeatureTag.liga, False)}
}
Dim noRects = New List(Of ObjectRect)()
Dim tl As TextLayout = Nothing
Dim tso = New TextSplitOptions() With
{
.RestObjectRects = noRects,
.AllowMovingAllToRest = True
}
Dim rcPrevTop As LayoutRect = Nothing
Dim rcPrevLeft As LayoutRect = Nothing
Dim paragraphStarted = False
While True
Dim r0 = view.CreateVisual(AddressOf DrawTextFragment).LayoutRect
If rcPrevLeft IsNot Nothing Then
r0.SetTop(rcPrevLeft, AnchorParam.Top)
ElseIf rcPrevTop IsNot Nothing Then
r0.SetTop(rcPrevTop, AnchorParam.Bottom, If(paragraphStarted, lineSpacing, paragraphSpacing))
Else
r0.SetTop(rcMargin, AnchorParam.Top)
End If
If rcPrevLeft Is Nothing Then
r0.SetLeft(rcMargin, AnchorParam.Left)
Else
r0.SetLeft(rcPrevLeft, AnchorParam.Right)
End If
r0.SetHeight(rowHeight)
r0.AppendMaxRight(rcMargin, AnchorParam.Right)
Dim r1 = view.CreateSpace().LayoutRect
r1.SetTop(r0, AnchorParam.Top)
r1.SetHeight(rowHeight)
r1.SetLeft(r0, AnchorParam.Right)
r1.AppendMaxRight(rcMargin, AnchorParam.Right)
r0.AppendMaxRight(c1_outer, ContourPosition.FirstInOutside)
r0.AppendMaxRight(c2_outer, ContourPosition.FirstInOutside)
r1.AppendMaxRight(c1_outer, ContourPosition.NextOutOutside)
r1.AppendMaxRight(c2_outer, ContourPosition.NextOutOutside)
surf.PerformLayout()
If Not paragraphStarted Then
'' It is important to have the ObjectRects property set
'' to a not null value (an empty list works well) and
'' the AllowOverhangingWords property set to true.
tl = g.CreateTextLayout()
tl.ObjectRects = noRects
tl.TextAlignment = TextAlignment.Justified
tl.AllowOverhangingWords = True
tl.FirstLineIndent = 40F
tl.JustifiedTextExtension = 0.1F
tl.Append(Util.LoremIpsum(1), tf)
tl.MaxWidth = r0.Width
tl.MaxHeight = r0.Height
CType(r0.Tag, Visual).Tag = tl
If Not tl.PerformLayout() Then
paragraphStarted = True
End If
Else
tso.RestMaxWidth = r0.Width
tso.RestMaxHeight = r0.Height
Dim rest As TextLayout = Nothing
Dim res = tl.Split(tso, rest)
If res <> SplitResult.CannotSplit Then
tl = rest
CType(r0.Tag, Visual).Tag = rest
If tl.PerformLayout() Then
paragraphStarted = False
End If
End If
End If
If paragraphStarted AndAlso r1.Width > 0F Then
rcPrevLeft = r1
Else
CType(r1.Tag, Space).Detach()
Dim spacing = If(paragraphStarted, lineSpacing, paragraphSpacing)
If rcMargin.P2Y - r0.P2Y < spacing + rowHeight Then
Exit While
End If
rcPrevLeft = Nothing
rcPrevTop = r0
End If
End While
tl.Truncate(TrimmingGranularity.Word)
'' The second View showing text in the ellipse.
Dim view2 = surf.CreateView(pageSize.Width \ 3, pageSize.Height \ 2).Translate(520, 260).Rotate(15)
tf = New TextFormat(tf) With
{
.ForeColor = Color.Purple,
.FontSize = 14
}
tl = g.CreateTextLayout()
tl.ObjectRects = noRects
tl.TextAlignment = TextAlignment.Center
tl.AllowOverhangingWords = True
tl.Append(Util.LoremIpsum(1), tf)
rcPrevTop = Nothing
paragraphStarted = False
While True
Dim r0 = view2.CreateSpace().LayoutRect
If rcPrevTop IsNot Nothing Then
r0.SetTop(rcPrevTop, AnchorParam.Bottom, 4)
Else
r0.SetTop(Nothing, AnchorParam.Top)
End If
r0.SetLeft(Nothing, AnchorParam.Left)
r0.SetHeight(18)
r0.AppendMaxRight(Nothing, AnchorParam.Right)
Dim r1 = view2.CreateVisual(AddressOf DrawTextFragment).LayoutRect
r1.SetTop(r0, AnchorParam.Top)
r1.SetHeight(18)
r1.SetLeft(r0, AnchorParam.Right)
r1.AppendMaxRight(Nothing, AnchorParam.Right)
r0.AppendMaxRight(c2_inner, ContourPosition.FirstInInside)
r1.AppendMaxRight(c2_inner, ContourPosition.NextOutInside)
surf.PerformLayout()
If r1.Width = 0F Then
CType(r1.Tag, Space).Detach()
If paragraphStarted Then
Exit While
End If
ElseIf Not paragraphStarted Then
tl.MaxWidth = r1.Width
tl.MaxHeight = r1.Height
CType(r1.Tag, Visual).Tag = tl
If tl.PerformLayout() Then
Exit While
End If
paragraphStarted = True
Else
tso.RestMaxWidth = r1.Width
tso.RestMaxHeight = r1.Height
Dim rest As TextLayout = Nothing
Dim res = tl.Split(tso, rest)
If res = SplitResult.FitAll Then
CType(r1.Tag, Space).Detach()
Exit While
End If
If res = SplitResult.Split Then
CType(r1.Tag, Visual).Tag = rest
tl = rest
End If
End If
rcPrevTop = r0
End While
tl.Truncate(TrimmingGranularity.Word)
surf.Render(g)
End Sub
''
'' Common utility classes and methods.
''
Private Class FigureCaption
Public ReadOnly Property Number As Integer
Public ReadOnly Property Description As String
Public ReadOnly Property Code As String
Public Sub New(number As Integer, description As String, Optional code As String = Nothing)
Me.Number = number
Me.Description = description
Me.Code = code
End Sub
End Class
Private Shared Sub DrawTextFragment(g As GcGraphics, v As Visual)
Dim tl = TryCast(v.Tag, TextLayout)
If tl IsNot Nothing Then
g.DrawTextLayout(tl, New PointF(0, 0))
End If
End Sub
Private Shared Sub CreateFigure1(surf As Surface, ByRef c_outer As Contour)
'' A View for the yellow polygon.
Dim view = surf.CreateView(0, 0).Translate(120, -40).Rotate(40)
Dim lv = view.LayoutView
Dim c = lv.CreateContour()
Dim v = view.CreateVisual(c, True, Sub(gr As GcGraphics, vis As Visual)
gr.FillPolygon(vis.Points, Color.LemonChiffon)
gr.DrawPolygon(vis.Points, Color.Green, 3)
End Sub)
Dim rect = v.LayoutRect
rect.AnchorTopLeft(Nothing, 100, 150, 170, 70)
c.AddPoints(New AnchorPoint() {
rect.CreatePoint(0, 0, -20, -20),
rect.CreatePoint(1, 0, 20, -20),
rect.CreatePoint(1, 0, 20, -120),
rect.CreatePoint(1, 0, 120, -120),
rect.CreatePoint(1, 1, 120, 20),
rect.CreatePoint(0, 1, -20, 20)
})
surf.PerformLayout()
Dim points = c.MapToView(lv)
'' To make the outer offset from the Contour we convert
'' the Contour to a GraphicsPath, then apply the Widen
'' method with a thick pen. The resulting figure is
'' used for creating the outer Contour.
Dim gp = New GraphicsPath(New FreeFormPolygon(points))
Dim gp2 = gp.Widen(New GCDRAW.Pen(Color.White, 7 * 2))
Dim fig_outer = gp2.Figures(0)
fig_outer.Flatten()
Dim outer_points = fig_outer.TransformedPoints
c_outer = lv.CreateContour()
For i = 0 To outer_points.Length - 1
Dim p = outer_points(i)
c_outer.AddPoint(lv.CreatePoint(0F, 0F, p.X, p.Y))
Next
End Sub
Private Shared Sub CreateFigure2(surf As Surface, ByRef c_outer As Contour, ByRef c_inner As Contour)
'' A View for the rotated ellipse.
Dim view = surf.CreateView(360, 150).Translate(450, 530).Rotate(-40)
Dim lv = view.LayoutView
Dim c = lv.CreateContour()
view.CreateVisual(c, False, Sub(gr As GcGraphics, vis As Visual)
gr.DrawPolygon(vis.Points, Color.DeepPink, 3)
End Sub)
'' To make the inner and the outer offsets from the ellipse
'' we convert the elliptic figure to an array of points which
'' is used later for creating a GraphicsPath. Then, we call
'' the GraphicsPath.Widen method with a thick pen.
'' The resulting outer and inner figures can be converted
'' into new contours for later use in constraints.
Dim ef As IFigure = New EllipticFigure(lv.AsRectF())
ef.Flatten()
Dim points = ef.TransformedPoints
Dim count = points.Length
Dim list = New List(Of AnchorPoint)(count)
For i = 0 To count - 1
Dim p = points(i)
list.Add(lv.CreatePoint(0, 0, p.X, p.Y))
Next
c.AddPoints(list)
Dim gp = New GraphicsPath(ef)
Dim gp2 = gp.Widen(New GCDRAW.Pen(Color.White, 7 * 2))
Dim fig_outer = gp2.Figures(0)
Dim fig_inner = gp2.Figures(1)
fig_outer.Flatten()
Dim outer_points = fig_outer.TransformedPoints
c_outer = lv.CreateContour()
For i = 0 To outer_points.Length - 1
Dim p = outer_points(i)
c_outer.AddPoint(lv.CreatePoint(0F, 0F, p.X, p.Y))
Next
fig_inner.Flatten()
Dim inner_points = fig_inner.TransformedPoints
c_inner = lv.CreateContour()
For i = 0 To inner_points.Length - 1
Dim p = inner_points(i)
c_inner.AddPoint(lv.CreatePoint(0F, 0F, p.X, p.Y))
Next
End Sub
Private Shared ReadOnly FormatBox As TextFormat = New TextFormat() With
{
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSans.ttf")),
.FontSize = 14,
.FontSizeInGraphicUnits = True,
.ForeColor = BoxColor
}
Private Shared ReadOnly FormatDesc As TextFormat = New TextFormat(FormatBox) With
{
.FontSize = 12,
.ForeColor = DescColor
}
Private Shared ReadOnly FormatCaption As TextFormat = New TextFormat(FormatDesc) With
{
.FontBold = True
}
Private Shared ReadOnly FormatCode As TextFormat = New TextFormat(FormatDesc) With
{
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeMono.ttf")),
.ForeColor = CodeColor
}
Private Shared Sub DrawView(g As GcGraphics, v As Visual)
Dim rect = v.AsRectF()
g.FillRectangle(rect, Color.FromArgb(31, 82, 100))
g.DrawRectangle(rect, New GCDRAW.Pen(Color.FromArgb(200, 200, 200), 1) With
{
.DashPattern = New Single() {7, 3}
})
Dim fc = TryCast(v.Tag, FigureCaption)
If fc IsNot Nothing Then
Dim tl = g.CreateTextLayout()
tl.Append($"Figure {fc.Number}. ", FormatCaption)
tl.AppendLine(fc.Description, FormatDesc)
If fc.Code IsNot Nothing Then
tl.Append(fc.Code, FormatCode)
End If
g.DrawTextLayout(tl, New PointF(0, v.Height + 5))
End If
End Sub
Private Shared Sub DrawVertGuideline(g As GcGraphics, v As Visual)
g.DrawLine(New PointF(0, 0), New PointF(0, v.Height), New GCDRAW.Pen(BoxColor, 1) With
{
.DashPattern = New Single() {1, 2}
})
Dim s = TryCast(v.Tag, String)
If s IsNot Nothing Then
Dim tl = g.CreateTextLayout()
tl.Append(s, FormatDesc)
tl.PerformLayout()
Dim rect = tl.ContentRectangle
rect.X = -rect.Width * 0.5F
rect.Y = 10
rect.Inflate(3, 1)
g.FillRoundRect(rect, 3, RectColor)
g.DrawTextLayout(tl, New PointF(rect.X + 3, rect.Y + 1))
End If
End Sub
Private Shared Sub DrawRect(g As GcGraphics, v As Visual)
Dim rect = v.AsRectF()
g.FillRectangle(rect, RectColor)
g.DrawRectangle(rect, New GCDRAW.Pen(BoxColor, 1))
Dim s = TryCast(v.Tag, String)
If s IsNot Nothing Then
Dim tl = g.CreateTextLayout()
tl.MaxWidth = v.Width
tl.MaxHeight = v.Height
tl.TextAlignment = TextAlignment.Center
tl.ParagraphAlignment = ParagraphAlignment.Center
tl.Append(s, FormatBox)
g.DrawTextLayout(tl, New PointF(0, 0))
End If
End Sub
Private Shared Sub DrawLineWithLeftArrow(g As GcGraphics, v As Visual)
Dim y = v.Height * 0.5F
g.DrawLine(New PointF(5, y), New PointF(v.Width, y), New GCDRAW.Pen(BoxColor, 0.7F))
DrawLeftArrow(g, 0, y)
End Sub
Private Shared Sub DrawLineWithRightArrow(g As GcGraphics, v As Visual)
Dim y = v.Height * 0.5F
g.DrawLine(New PointF(0, y), New PointF(v.Width - 5, y), New GCDRAW.Pen(BoxColor, 0.7F))
DrawRightArrow(g, v.Width, y)
End Sub
Private Shared Sub DrawLeftRightLines(g As GcGraphics, v As Visual)
Dim y = v.Height * 0.33F
g.DrawLine(New PointF(5, y), New PointF(v.Width, y), New GCDRAW.Pen(BoxColor, 0.7F))
DrawLeftArrow(g, 0, y)
y = v.Height * 0.66F
g.DrawLine(New PointF(0, y), New PointF(v.Width - 5, y), New GCDRAW.Pen(BoxColor, 0.7F))
DrawRightArrow(g, v.Width, y)
End Sub
Private Shared Sub DrawVertLineWithLeftArrow(g As GcGraphics, v As Visual)
Dim x = v.Width * 0.5F
g.DrawLines(New PointF() {
New PointF(5, 0),
New PointF(x, 0),
New PointF(x, v.Height),
New PointF(v.Width, v.Height)
}, New GCDRAW.Pen(BoxColor, 0.7F))
DrawLeftArrow(g, 0, 0)
End Sub
Private Shared Sub DrawLineWithUpArrow(g As GcGraphics, v As Visual)
Dim x = v.Width * 0.5F
g.DrawLine(New PointF(x, 5), New PointF(x, v.Height), New GCDRAW.Pen(BoxColor, 0.7F))
DrawUpArrow(g, x, 0)
End Sub
Private Shared Sub DrawLeftArrow(g As GcGraphics, x As Single, y As Single)
Dim pts = New PointF() {
New PointF(x, y),
New PointF(x + 8, y - 2.5F),
New PointF(x + 8, y + 2.5F)
}
g.FillPolygon(pts, BoxColor)
End Sub
Private Shared Sub DrawRightArrow(g As GcGraphics, x As Single, y As Single)
Dim pts = New PointF() {
New PointF(x, y),
New PointF(x - 8, y + 2.5F),
New PointF(x - 8, y - 2.5F)
}
g.FillPolygon(pts, BoxColor)
End Sub
Private Shared Sub DrawUpArrow(g As GcGraphics, x As Single, y As Single)
Dim pts = New PointF() {
New PointF(x, y),
New PointF(x + 2.5F, y + 8),
New PointF(x - 2.5F, y + 8)
}
g.FillPolygon(pts, BoxColor)
End Sub
End Class