2
0
Unknown 6 жил өмнө
parent
commit
b59af2aac9

+ 248 - 7
vectoredit/umain.lfm

@@ -1,10 +1,10 @@
 object Form1: TForm1
 object Form1: TForm1
-  Left = 374
-  Height = 475
-  Top = 0
+  Left = 440
+  Height = 522
+  Top = 15
   Width = 981
   Width = 981
   Caption = 'Vector Edit'
   Caption = 'Vector Edit'
-  ClientHeight = 475
+  ClientHeight = 522
   ClientWidth = 981
   ClientWidth = 981
   KeyPreview = True
   KeyPreview = True
   OnCreate = FormCreate
   OnCreate = FormCreate
@@ -15,7 +15,7 @@ object Form1: TForm1
   LCLVersion = '1.6.0.4'
   LCLVersion = '1.6.0.4'
   object BGRAVirtualScreen1: TBGRAVirtualScreen
   object BGRAVirtualScreen1: TBGRAVirtualScreen
     Left = 60
     Left = 60
-    Height = 417
+    Height = 464
     Top = 58
     Top = 58
     Width = 921
     Width = 921
     OnRedraw = BGRAVirtualScreen1Redraw
     OnRedraw = BGRAVirtualScreen1Redraw
@@ -30,7 +30,7 @@ object Form1: TForm1
   end
   end
   object BCPanelToolChoice: TBCPanel
   object BCPanelToolChoice: TBCPanel
     Left = 0
     Left = 0
-    Height = 417
+    Height = 464
     Top = 58
     Top = 58
     Width = 60
     Width = 60
     Align = alLeft
     Align = alLeft
@@ -92,7 +92,7 @@ object Form1: TForm1
     TabOrder = 1
     TabOrder = 1
     object ToolBarTools: TToolBar
     object ToolBarTools: TToolBar
       Left = 1
       Left = 1
-      Height = 415
+      Height = 462
       Top = 1
       Top = 1
       Width = 55
       Width = 55
       Align = alLeft
       Align = alLeft
@@ -176,6 +176,16 @@ object Form1: TForm1
         OnClick = ToolButtonClick
         OnClick = ToolButtonClick
         Style = tbsCheck
         Style = tbsCheck
       end
       end
+      object ToolButtonPhongShape: TToolButton
+        Left = 1
+        Hint = 'Phong-shaded shape'
+        Top = 385
+        Caption = 'ToolButtonPhongShape'
+        Grouped = True
+        ImageIndex = 70
+        OnClick = ToolButtonClick
+        Style = tbsCheck
+      end
     end
     end
   end
   end
   object BCPanelToolbar: TBCPanel
   object BCPanelToolbar: TBCPanel
@@ -42318,4 +42328,235 @@ object Form1: TForm1
       0000000000000000000000000000
       0000000000000000000000000000
     }
     }
   end
   end
+  object PhongImageList: TBGRAImageList
+    left = 536
+    top = 160
+    Bitmap = {
+      4C69070000001000000010000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000202FF7F0202FFFF0202FFFF0202
+      FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202
+      FFFF0202FFFF0202FF7F000000000202FF7F0E0EFFFF0404FFFF0404FFFF0404
+      FFFF0404FFFF0404FFFF0404FFFF0404FFFF0404FFFF0404FFFF0404FFFF0404
+      FFFF0404FFFF00008BFF0000677F0202FFFF0404FFFFDADAFFFF9D9DFFFF9C9C
+      FFFF9B9BFFFF9A9AFFFF9999FFFF9898FFFF9797FFFF9696FFFF9595FFFF9494
+      FFFF1414E1FF000069FF000067FF0202FFFF0404FFFF9A9AFFFF6F6FFFFF6E6E
+      FFFF6E6EFFFF6D6DFFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6A
+      FFFF0808A2FF000069FF000067FF0202FFFF0404FFFF9999FFFF6E6EFFFF6E6E
+      FFFF6D6DFFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6A
+      FFFF0808A2FF000069FF000068FF0202FFFF0404FFFF9898FFFF6E6EFFFF6D6D
+      FFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6A6A
+      FEFF0808A2FF000069FF000068FF0202FFFF0404FFFF9797FFFF6D6DFFFF6D6D
+      FFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6A6AFEFF6969
+      FEFF0808A1FF000069FF000068FF0202FFFF0404FFFF9696FFFF6D6DFFFF6C6C
+      FFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6969FFFF6969FEFF6969
+      FEFF0808A1FF00006AFF000068FF0202FFFF0404FFFF9494FFFF6C6CFFFF6C6C
+      FFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6969FFFF6969FEFF6969FEFF6868
+      FDFF0808A1FF00006AFF000068FF0202FFFF0404FFFF1414E3FF0808A4FF0808
+      A4FF0808A4FF0808A4FF0808A4FF0808A3FF0808A3FF0808A3FF0808A3FF0808
+      A3FF000077FF00006AFF000068FF0202FF7F00008BFF000069FF000069FF0000
+      69FF000069FF00006AFF00006AFF00006AFF00006AFF00006AFF00006AFF0000
+      6AFF00006AFF00005EFF0000687F000000000000677F000067FF000067FF0000
+      68FF000068FF000068FF000068FF000068FF000068FF000068FF000068FF0000
+      68FF000069FF0000697F00000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000202
+      FF950202FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202FFFF0202FFA00000
+      000000000000000000000000000000000000000000000202FF7F0202FFFF0707
+      FFFF0808FFFF0404FFFF0404FFFF0404FFFF0404FFFF0404FFFF0202FFFF0202
+      FFFF2121FF840000000000000000000000000202FF7F0E0EFFFF0404FFFF5252
+      FFFF9B9BFFFF9A9AFFFF9999FFFF9898FFFF9797FFFF9696FFFF0404FFFF1212
+      FFFF3B3BA6FF0000677F00000000000000000202FFFF1A1AFFFFDADAFFFF9D9D
+      FFFF6E6EFFFF6D6DFFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF9494FFFF3A3A
+      E6FF3E3E90FF17176FFF000000000202FFCE1212FFFE5B5BFFFF9A9AFFFF6F6F
+      FFFF6D6DFFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6969
+      DCFF10106EFF000067FF000068C80202FFFF0404FFFF9898FFFF6E6EFFFF6D6D
+      FFFF6D6DFFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6C6C
+      FEFF0808A2FF000069FF000068FF0202FFFF0404FFFF9797FFFF6D6DFFFF6D6D
+      FFFF6C6CFFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6A6AFEFF6B6B
+      FEFF0808A1FF000069FF000068FE0202FFC70202FFFF3C3CFFFF9494FFFF6C6C
+      FFFF6C6CFFFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6969FFFF6969FDFF3C3C
+      B6FF00006AFF000068FF000068C9000000000202FFFF1212FFFF4949EAFF4C4C
+      CDFF6B6BFFFF6B6BFFFF6A6AFFFF6A6AFFFF6969FFFF6F6FFEFF3636B4FF0000
+      77FF00006AFF000068FF00000000000000002B2BFF873C3CA6FF464699FF0000
+      69FF0808A4FF0808A4FF0808A4FF0808A3FF0808A3FF0808A3FF00006AFF0000
+      6AFF00005EFF0000687F000000000000000000000000222277843B3B8DFF0000
+      67FF000069FF00006AFF00006AFF00006AFF00006AFF00006AFF000068FF0000
+      69FF0000697F00000000000000000000000000000000000000009D9DFF050000
+      689C000068FF000068FF000068FF000068FF000068FF000068FF000068A60000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000121CFF3B151EFF87101AFFA50916FFA50414FF870213FF3B000000000000
+      00000000000000000000000000000000000000000000000000001A22FF3C262C
+      FFC11C24FFFC1D24FFFF171FFFFF0F19FFFF0715FFFF0313FFFC0011E4C10010
+      DC3C00000000000000000000000000000000000000002027FF5C242BFFEF363B
+      FFFF4044FFFF3F43FFFF3237FFFF2027FFFF111BFFFF0615FFFF0212F5FF0010
+      D6EF000EBE5C0000000000000000000000001A22FF3C242BFFEF4146FFFF5E61
+      FFFF7073FFFF7072FFFF5B5EFFFF3B3FFFFF1E25FFFF0B17FFFF0312F0FF000F
+      D0FF000DABEF000C9D3C0000000000000000262CFFC1363BFFFF5E61FFFF888A
+      FFFFA8A9FFFFABADFFFF8D8FFFFF5B5EFFFF2D32FFFF101AFFFF0412E7FF000F
+      C5FF000CA0FF000CA0C100000000121CFF3B1C24FFFC4044FFFF7073FFFFA8A9
+      FFFFD6D6FFFFE0E1FFFFBBBCFFFF7679FFFF383DFFFF131CFBFF0511D9FF000D
+      B5FF000C9CFF000B93FC000B8F3B151EFF871D24FFFF3F43FFFF7072FFFFABAD
+      FFFFE0E1FFFFF1F1FFFFC9CAFFFF7D7FFFFF383DFFFF121AE9FF040FC5FF000C
+      9FFF000B97FF000B8FFF000B8E87101AFFA4171FFFFF3237FFFF5B5EFFFF8D8F
+      FFFFBBBCFFFFC9CAFFFFA6A7FFFF6466FFFF2A30F6FF0C15D2FF030DABFF000B
+      99FF000B91FF000A8AFF000A88A40916FFA40F19FFFF2027FFFF3B3FFFFF5B5E
+      FFFF7679FFFF7D7FFFFF6466FFFF393EFAFF171ED9FF060FB4FF000C9BFF000B
+      93FF000A8BFF000A84FF000A81A40414FF870715FFFF111BFFFF1E25FFFF2D32
+      FFFF383DFFFF383DFFFF2A30F6FF171ED9FF0811B7FF020C9CFF000B94FF000A
+      8CFF000A85FF00097EFF00097A870213FF3B0313FFFC0615FFFF0B17FFFF101A
+      FFFF131CFBFF121AE9FF0C15D2FF060FB4FF020C9CFF000B94FF000A8CFF000A
+      85FF00097FFF000978FC0009773B000000000011E4C10212F5FF0312F0FF0412
+      E7FF0511D9FF040FC5FF030DABFF000C9BFF000B94FF000A8CFF000A85FF0009
+      7FFF000979FF000974C100000000000000000010DC3C0010D6EF000FD0FF000F
+      C5FF000DB5FF000C9FFF000B99FF000B93FF000A8CFF000A85FF00097FFF0009
+      79FF000973EF0008713C000000000000000000000000000EBE5C000DABEF000C
+      A0FF000C9CFF000B97FF000B91FF000A8BFF000A85FF00097FFF000979FF0009
+      73EF0008715C0000000000000000000000000000000000000000000C9D3C000C
+      A0C1000B93FC000B8FFF000A8AFF000A84FF00097EFF000978FC000974C10008
+      713C000000000000000000000000000000000000000000000000000000000000
+      0000000B8F3B000B8E87000A88A5000A81A500097A870009773B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00005A5DFF3B363BFF872B31FFA52A30FFA53439FF875458FF3B000000000000
+      0000000000000000000000000000000000000000000000000000BABBFF3C7274
+      FFC19C9EFFFC5F62FFFF373CFFFF1F27FFFF101AFFFF0613ECFC0C18FFC12C31
+      F53C0000000000000000000000000000000000000000FAFAFF5CCFD0FFEF989A
+      FFFF7E80FFFF5A5DFFFF393EFFFF1E25FFFF0E19FFFF0513F2FF0210D1FF020E
+      B3EF020CA15C000000000000000000000000BABBFF3CCFD0FFEFA8A9FFFFA2A3
+      FFFF9092FFFF696BFFFF3D41FFFF1D24FFFF0A16FFFF0311E1FF000EC0FF000C
+      9EFF000B9AEF000A8B3C00000000000000007274FFC1989AFFFFA2A3FFFFA9AA
+      FFFFA1A3FFFF7E80FFFF4549FFFF1A22FFFF0614F9FF000FC9FF000C9FFF000B
+      96FF000B91FF000A81C1000000005A5DFF3B9C9EFFFC7E80FFFF9092FFFFA1A3
+      FFFFAEAFFFFF999BFFFF5054FFFF161FFFFF0311DFFF000C9FFF000B94FF000B
+      8DFF000A88FF000A8BFC00097A3B363BFF875F62FFFF5A5DFFFF696BFFFF7E80
+      FFFF999BFFFFB6B7FFFF696CFFFF0E19FFFF000C9FFF000B8FFF000A86FF000A
+      81FF00097DFF00097DFF000871872B31FFA4373CFFFF393EFFFF3D41FFFF4549
+      FFFF5054FFFF696CFFFFC2C2FFFF020CA2FF00097FFF000979FF000976FF0009
+      74FF000974FF000973FF00086FA42A30FFA41F27FFFF1E25FFFF1D24FFFF1A22
+      FFFF161FFFFF0E19FFFF020CA2FF000760FF000761FF000865FF000868FF0008
+      69FF00086AFF00086CFF000870A43439FF87101AFFFF0E19FFFF0A16FFFF0614
+      F9FF0311DFFF000C9FFF00097FFF000761FF000657FF00075AFF00075DFF0007
+      60FF000763FF000865FF000972875458FF3B0613ECFC0513F2FF0311E1FF000F
+      C9FF000C9FFF000B8FFF000979FF000865FF00075AFF000657FF000758FF0007
+      5BFF00075DFF000761FC00097B3B000000000C18FFC10210D1FF000EC0FF000C
+      9FFF000B94FF000A86FF000976FF000868FF00075DFF000758FF000757FF0007
+      59FF00075AFF000764C100000000000000002C31F53C020EB3EF000C9EFF000B
+      96FF000B8DFF000A81FF000974FF000869FF000760FF00075BFF000759FF0007
+      58FF00075FEF0009793C000000000000000000000000020CA15C000B9AEF000B
+      91FF000A88FF00097DFF000974FF00086AFF000763FF00075DFF00075AFF0007
+      5FEF0008695C0000000000000000000000000000000000000000000A8B3C000A
+      81C1000A8BFC00097DFF000973FF00086CFF000865FF000761FC000764C10009
+      793C000000000000000000000000000000000000000000000000000000000000
+      000000097A3B0008718700086FA5000870A50009728700097B3B000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000007C7EFFA60000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007D7FFF716769FFFF4145FF6500000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000007F81FFD76B6EFFFF494DFFCA00000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007779FF718688FFFF7072FFFF3035FFFE131CFF54000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000007C7EFFD7888AFFFF7376FFFF3D41FFFF1E26FFBE000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00005659FF717476FFFF8A8CFFFF7779FFFF474BFFFF141DFFFB0615FF440000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00006063FFD77B7DFFFF8D8EFFFF7B7DFFFF4F53FFFF1F26FFFF0D18FFB20000
+      0000000000000000000000000000000000000000000000000000000000003A3F
+      FF71575AFFFF8183FFFF8F90FFFF7E80FFFF575AFFFF292FFFFF0916FFF70313
+      FF3400000000000000000000000000000000000000000000000000000000464A
+      FFD76265FFFF8688FFFF9193FFFF8183FFFF5D60FFFF3237FFFF101AFFFF0615
+      FFA7000000000000000000000000000000000000000000000000282EFF713F43
+      FFFF6C6EFFFF8B8DFFFF9395FFFF8486FFFF6365FFFF3B3FFFFF1821FFFF0414
+      FFF20013FF2600000000000000000000000000000000000000003338FFD74B4F
+      FFFF7476FFFF8F91FFFF9597FFFF8789FFFF686BFFFF4246FFFF2027FFFF0916
+      FFFF0414FF9A000000000000000000000000000000001C24FF712E34FFFF5659
+      FFFF7B7DFFFF9394FFFF9899FFFF898BFFFF6D6FFFFF494DFFFF272DFFFF0F19
+      FFFF0213FFEC0013FF19000000000000000000000000262CFFD73A3EFFFF6063
+      FFFF8183FFFF9697FFFF9A9BFFFF8C8EFFFF7174FFFF5053FFFF2F34FFFF151E
+      FFFF0514FFFF0213FF8C0000000000000000151EFF712329FFFF4448FFFF696B
+      FFFF8789FFFF999AFFFF9C9DFFFF8F91FFFF7578FFFF5659FFFF353AFFFF1B22
+      FFFF0916FFFF0213FFE30012F60A000000001D24FFD72D32FFFF4E52FFFF7073
+      FFFF8C8EFFFF9C9EFFFF9E9FFFFF9193FFFF7A7CFFFF5B5EFFFF3C40FFFF2128
+      FFFF0E19FFFF0414FFFF0013FF7D141DFF711A22FFFF363BFFFF575AFFFF7779
+      FFFF9192FFFF9FA1FFFFA0A2FFFF9496FFFF7D7FFFFF6063FFFF4246FFFF272D
+      FFFF121CFFFF0615FFFF0313FFDA000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000001D24FFFF1D24FFFF1D24FFFF1D24FFFF1C24
+      FFFF1C24FFFF1C24FFFF1C24FFFF1C23FFFF1C23FFFF1C23FFFF1B23FFFF1B23
+      FFFF1B23FFFF1B22FFFF1A22FFFF3338FFFF3338FFFF3338FFFF3238FFFF3237
+      FFFF3237FFFF3237FFFF3137FFFF3136FFFF3136FFFF3136FFFF3035FFFF3035
+      FFFF3035FFFF2F35FFFF2F34FFFF8486FFFF8486FFFF8385FFFF8384FFFF8284
+      FFFF8183FFFF8183FFFF8082FFFF7F81FFFF7F81FFFF7E80FFFF7D7FFFFF7D7F
+      FFFF7C7EFFFF7B7DFFFF7A7CFFFFE9E9FFFFE8E8FFFFE7E7FFFFE6E6FFFFE5E5
+      FFFFE4E4FFFFE3E3FFFFE2E2FFFFE1E1FFFFE0E0FFFFDEDFFFFFDDDEFFFFDCDC
+      FFFFDBDBFFFFD9DAFFFFD8D9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+      FFFFFFFFFFFFFEFEFFFFFCFCFFFFC2C3FFFFC2C3FFFFC1C2FFFFC1C1FFFFC0C1
+      FFFFBFC0FFFFBEBFFFFFBEBFFFFFBDBEFFFFBCBDFFFFBBBCFFFFBBBCFFFFBABB
+      FFFFB9BAFFFFB8B9FFFFB7B8FFFF5458FFFF5458FFFF5457FFFF5457FFFF5457
+      FFFF5357FFFF5356FFFF5356FFFF5256FFFF5256FFFF5255FFFF5255FFFF5155
+      FFFF5154FFFF5154FFFF5054FFFF151EFFFF151EFFFF151EFFFF151EFFFF151E
+      FFFF151EFFFF151EFFFF151EFFFF151EFFFF151EFFFF151EFFFF151EFFFF151E
+      FFFF151EFFFF151EFFFF151EFFFF0313F8FF0313F7FF0313F7FF0313F7FF0313
+      F7FF0313F7FF0313F6FF0313F6FF0313F6FF0313F6FF0313F5FF0313F5FF0313
+      F5FF0313F5FF0313F4FF0313F4FF0010DDFF0010DDFF0010DDFF0010DDFF0010
+      DCFF0010DCFF0010DCFF0010DCFF0010DCFF0010DCFF0010DBFF0010DBFF0010
+      DBFF0010DBFF0010DBFF0010DBFF000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000151EFFFF272D
+      FFFF6F71FFFFD2D3FFFFFFFFFFFFCCCDFFFF6164FFFF1C23FFFF0414FFFF0212
+      F1FF000000000000000000000000000000000000000000000000151EFFFF272D
+      FFFF6E71FFFFD1D2FFFFFFFFFFFFCBCCFFFF6063FFFF1B23FFFF0414FFFF0212
+      F1FF000000000000000000000000000000000000000000000000151EFFFF272D
+      FFFF6E70FFFFD0D1FFFFFFFFFFFFCACBFFFF6063FFFF1B23FFFF0414FFFF0212
+      F1FF000000000000000000000000000000000000000000000000151EFFFF262C
+      FFFF6D70FFFFCFD0FFFFFFFFFFFFC9CAFFFF6063FFFF1B23FFFF0414FFFF0212
+      F1FF000000000000000000000000000000000000000000000000141EFFFF262C
+      FFFF6C6FFFFFCECFFFFFFFFFFFFFC8C9FFFF5F62FFFF1B23FFFF0414FFFF0212
+      F0FF000000000000000000000000000000000000000000000000141EFFFF262C
+      FFFF6C6EFFFFCDCDFFFFFFFFFFFFC7C8FFFF5F62FFFF1B23FFFF0414FFFF0212
+      F0FF000000000000000000000000000000000000000000000000141DFFFF262C
+      FFFF6B6DFFFFCCCDFFFFFEFEFFFFC6C7FFFF5E61FFFF1B23FFFF0414FFFF0212
+      F0FF000000000000000000000000000000000000000000000000141DFFFF252C
+      FFFF6A6DFFFFCACBFFFFFDFDFFFFC5C6FFFF5E61FFFF1B23FFFF0414FFFF0212
+      EFFF000000000000000000000000000000000000000000000000141DFFFF252C
+      FFFF6A6CFFFFC9CAFFFFFBFBFFFFC5C5FFFF5D60FFFF1B23FFFF0414FFFF0212
+      EFFF000000000000000000000000000000000000000000000000141DFFFF252B
+      FFFF696CFFFFC8C9FFFFFAFAFFFFC3C4FFFF5D60FFFF1B22FFFF0414FFFF0212
+      EFFF000000000000000000000000000000000000000000000000141DFFFF252B
+      FFFF686BFFFFC7C7FFFFF8F9FFFFC2C3FFFF5D60FFFF1A22FFFF0414FFFF0212
+      EFFF000000000000000000000000000000000000000000000000141DFFFF242B
+      FFFF676AFFFFC5C6FFFFF7F7FFFFC1C2FFFF5C5FFFFF1A22FFFF0414FFFF0212
+      EEFF000000000000000000000000000000000000000000000000131DFFFF242B
+      FFFF6769FFFFC4C5FFFFF5F5FFFFC0C1FFFF5C5FFFFF1A22FFFF0414FFFF0212
+      EEFF000000000000000000000000000000000000000000000000131DFFFF242A
+      FFFF6669FFFFC3C4FFFFF4F4FFFFBFC0FFFF5B5EFFFF1A22FFFF0414FFFF0212
+      EEFF000000000000000000000000000000000000000000000000131DFFFF232A
+      FFFF6568FFFFC1C2FFFFF2F2FFFFBEBFFFFF5B5EFFFF1A22FFFF0414FFFF0212
+      EDFF000000000000000000000000000000000000000000000000131CFFFF232A
+      FFFF6467FFFFC0C1FFFFF1F1FFFFBDBEFFFF5A5DFFFF1A22FFFF0414FFFF0212
+      EDFF000000000000000000000000
+    }
+  end
 end
 end

+ 157 - 11
vectoredit/umain.pas

@@ -17,13 +17,17 @@ const
   GradRepetitionToStr : array[TBGRAGradientRepetition] of string = ('Pad', 'Repeat', 'Reflect', 'Sine');
   GradRepetitionToStr : array[TBGRAGradientRepetition] of string = ('Pad', 'Repeat', 'Reflect', 'Sine');
   ColorInterpToStr : array[TBGRAColorInterpolation] of string = ('sRGB', 'RGB', 'HSL CW', 'HSL CCW', 'Corr. HSL CW', 'Corr. HSL CCW');
   ColorInterpToStr : array[TBGRAColorInterpolation] of string = ('sRGB', 'RGB', 'HSL CW', 'HSL CCW', 'Corr. HSL CW', 'Corr. HSL CCW');
   TextureRepetitionToStr: array[TTextureRepetition] of string = ('No repetition', 'Repeat X', 'Repeat Y', 'Repeat both');
   TextureRepetitionToStr: array[TTextureRepetition] of string = ('No repetition', 'Repeat X', 'Repeat Y', 'Repeat both');
+  PhongShapeKindToStr: array[TPhongShapeKind] of string = ('Rectangle', 'Round rectangle', 'Half sphere', 'Cone top', 'Cone side',
+                     'Horizontal cylinder', 'Vertical cylinder');
 
 
 type
 type
-  TPaintTool = (ptHand, ptMoveBackFillPoint, ptRectangle, ptEllipse, ptPolyline, ptCurve, ptPolygon, ptClosedCurve);
+  TPaintTool = (ptHand, ptMoveBackFillPoint, ptRectangle, ptEllipse, ptPolyline, ptCurve, ptPolygon, ptClosedCurve,
+                ptPhongShape);
 
 
 const
 const
   PaintToolClass : array[TPaintTool] of TVectorShapeAny =
   PaintToolClass : array[TPaintTool] of TVectorShapeAny =
-    (nil, nil, TRectShape, TEllipseShape, TPolylineShape, TCurveShape, TPolylineShape, TCurveShape);
+    (nil, nil, TRectShape, TEllipseShape, TPolylineShape, TCurveShape, TPolylineShape, TCurveShape,
+     TPhongShape);
 
 
 function IsCreateShapeTool(ATool: TPaintTool): boolean;
 function IsCreateShapeTool(ATool: TPaintTool): boolean;
 
 
@@ -37,6 +41,7 @@ type
   TForm1 = class(TForm)
   TForm1 = class(TForm)
     BackImage: TImage;
     BackImage: TImage;
     BGRAFillImageList16: TBGRAImageList;
     BGRAFillImageList16: TBGRAImageList;
+    PhongImageList: TBGRAImageList;
     PenStyleImageList: TBGRAImageList;
     PenStyleImageList: TBGRAImageList;
     CurveImageList: TBGRAImageList;
     CurveImageList: TBGRAImageList;
     ButtonBackGradInterp: TBCButton;
     ButtonBackGradInterp: TBCButton;
@@ -66,6 +71,7 @@ type
     ToolBar2: TToolBar;
     ToolBar2: TToolBar;
     ButtonMoveBackFillPoints: TToolButton;
     ButtonMoveBackFillPoints: TToolButton;
     ToolBarJoinStyle: TToolBar;
     ToolBarJoinStyle: TToolBar;
+    ToolButtonPhongShape: TToolButton;
     ToolButtonJoinRound: TToolButton;
     ToolButtonJoinRound: TToolButton;
     ToolButton2: TToolButton;
     ToolButton2: TToolButton;
     ToolButtonJoinBevel: TToolButton;
     ToolButtonJoinBevel: TToolButton;
@@ -178,6 +184,11 @@ type
     FComboboxSplineStyle: TBCButton;
     FComboboxSplineStyle: TBCButton;
     FSplineToolbar: TToolBar;
     FSplineToolbar: TToolBar;
     FPenStyleMenu: TPopupMenu;
     FPenStyleMenu: TPopupMenu;
+    FPhongShapeKind: TPhongShapeKind;
+    FPhongShapeKindToolbar: TToolBar;
+    FPhongShapeAltitude,FPhongBorderSize: single;
+    FUpDownPhongShapeAltitude,
+    FUpDownPhongBorderSize: TBCTrackbarUpdown;
     FInRemoveShapeIfEmpty: Boolean;
     FInRemoveShapeIfEmpty: Boolean;
     procedure ComboBoxSplineStyleClick(Sender: TObject);
     procedure ComboBoxSplineStyleClick(Sender: TObject);
     function GetBackTexture: TBGRABitmap;
     function GetBackTexture: TBGRABitmap;
@@ -190,10 +201,13 @@ type
     procedure OnClickSplineStyleItem(ASender: TObject);
     procedure OnClickSplineStyleItem(ASender: TObject);
     procedure OnEditingChange({%H-}ASender: TObject; AOriginal: TBGRALayerCustomOriginal);
     procedure OnEditingChange({%H-}ASender: TObject; AOriginal: TBGRALayerCustomOriginal);
     procedure OnOriginalChange({%H-}ASender: TObject; AOriginal: TBGRALayerCustomOriginal);
     procedure OnOriginalChange({%H-}ASender: TObject; AOriginal: TBGRALayerCustomOriginal);
+    procedure OnPhongBorderSizeChange(Sender: TObject; AByUser: boolean);
+    procedure OnPhongShapeAltitudeChange(Sender: TObject; AByUser: boolean);
     procedure OnSelectShape(ASender: TObject; AShape: TVectorShape; APreviousShape: TVectorShape);
     procedure OnSelectShape(ASender: TObject; AShape: TVectorShape; APreviousShape: TVectorShape);
     procedure OnClickPenStyle(ASender: TObject);
     procedure OnClickPenStyle(ASender: TObject);
     procedure OnClickBackGradRepeat(ASender: TObject);
     procedure OnClickBackGradRepeat(ASender: TObject);
     procedure OnClickBackGradInterp(ASender: TObject);
     procedure OnClickBackGradInterp(ASender: TObject);
+    procedure PhongShapeKindClick(Sender: TObject);
     procedure SetBackColor(AValue: TBGRAPixel);
     procedure SetBackColor(AValue: TBGRAPixel);
     procedure SetBackGradEndColor(AValue: TBGRAPixel);
     procedure SetBackGradEndColor(AValue: TBGRAPixel);
     procedure SetBackGradInterp(AValue: TBGRAColorInterpolation);
     procedure SetBackGradInterp(AValue: TBGRAColorInterpolation);
@@ -206,6 +220,7 @@ type
     procedure SetPenJoinStyle(AValue: TPenJoinStyle);
     procedure SetPenJoinStyle(AValue: TPenJoinStyle);
     procedure SetPenStyle(AValue: TBGRAPenStyle);
     procedure SetPenStyle(AValue: TBGRAPenStyle);
     procedure SetPenWidth(AValue: single);
     procedure SetPenWidth(AValue: single);
+    procedure SetPhongShapeKind(AValue: TPhongShapeKind);
     procedure SetSplineStyle(AValue: TSplineStyle);
     procedure SetSplineStyle(AValue: TSplineStyle);
     procedure SplineToolbarClick(Sender: TObject);
     procedure SplineToolbarClick(Sender: TObject);
     procedure UpdateViewCursor(ACursor: TOriginalEditorCursor);
     procedure UpdateViewCursor(ACursor: TOriginalEditorCursor);
@@ -257,6 +272,7 @@ type
     property splineStyle: TSplineStyle read GetSplineStyle write SetSplineStyle;
     property splineStyle: TSplineStyle read GetSplineStyle write SetSplineStyle;
     property currentTool: TPaintTool read FCurrentTool write SetCurrentTool;
     property currentTool: TPaintTool read FCurrentTool write SetCurrentTool;
     property joinStyle: TPenJoinStyle read FPenJoinStyle write SetPenJoinStyle;
     property joinStyle: TPenJoinStyle read FPenJoinStyle write SetPenJoinStyle;
+    property phongShapeKind: TPhongShapeKind read FPhongShapeKind write SetPhongShapeKind;
   end;
   end;
 
 
 var
 var
@@ -266,8 +282,18 @@ implementation
 
 
 uses math, BGRAPen, BGRAThumbnail, BGRAGradientOriginal, uvectorclipboard;
 uses math, BGRAPen, BGRAThumbnail, BGRAGradientOriginal, uvectorclipboard;
 
 
+function CreateToolBar(AImages: TImageList): TToolbar;
+begin
+  result := TToolBar.Create(nil);
+  result.Align := alNone;
+  result.Height := AImages.Height + 9;
+  result.ShowHint:= true;
+  result.ShowCaptions:= false;
+  result.Images := AImages;
+end;
+
 procedure AddToolbarCheckButton(AToolbar: TToolbar; ACaption: string; AImageIndex: integer;
 procedure AddToolbarCheckButton(AToolbar: TToolbar; ACaption: string; AImageIndex: integer;
-          AOnClick: TNotifyEvent; ADown: boolean; AGrouped: boolean = true);
+          AOnClick: TNotifyEvent; ADown: boolean; AGrouped: boolean = true; ATag: PtrInt = 0);
 var
 var
   btn: TToolButton;
   btn: TToolButton;
 begin
 begin
@@ -280,6 +306,7 @@ begin
   btn.Grouped := AGrouped;
   btn.Grouped := AGrouped;
   btn.OnClick:= AOnClick;
   btn.OnClick:= AOnClick;
   btn.Parent := AToolbar;
   btn.Parent := AToolbar;
+  btn.Tag:= ATag;
 end;
 end;
 
 
 procedure EnableDisableToolButtons(AButtons: array of TToolButton; AEnabled: boolean);
 procedure EnableDisableToolButtons(AButtons: array of TToolButton; AEnabled: boolean);
@@ -393,6 +420,8 @@ begin
   FBackGradRepetition:= grPad;
   FBackGradRepetition:= grPad;
   FBackGradInterp:= ciLinearRGB;
   FBackGradInterp:= ciLinearRGB;
   FBackTexRepetition:= trRepeatBoth;
   FBackTexRepetition:= trRepeatBoth;
+  FPhongShapeAltitude := DefaultPhongShapeAltitudePercent;
+  FPhongBorderSize := DefaultPhongBorderSizePercent;
   UpdateTitleBar;
   UpdateTitleBar;
   UpdateBackComponentsVisibility;
   UpdateBackComponentsVisibility;
 end;
 end;
@@ -892,6 +921,7 @@ begin
   if ToolButtonCurve.Down then FCurrentTool:= ptCurve;
   if ToolButtonCurve.Down then FCurrentTool:= ptCurve;
   if ToolButtonPolygon.Down then FCurrentTool:= ptPolygon;
   if ToolButtonPolygon.Down then FCurrentTool:= ptPolygon;
   if ToolButtonClosedCurve.Down then FCurrentTool:= ptClosedCurve;
   if ToolButtonClosedCurve.Down then FCurrentTool:= ptClosedCurve;
+  if ToolButtonPhongShape.Down then FCurrentTool:= ptPhongShape;
 
 
   if currentTool <> ptMoveBackFillPoint then
   if currentTool <> ptMoveBackFillPoint then
     ButtonMoveBackFillPoints.Down := false;
     ButtonMoveBackFillPoints.Down := false;
@@ -1004,6 +1034,22 @@ begin
   RenderAndUpdate(slowShape);
   RenderAndUpdate(slowShape);
 end;
 end;
 
 
+procedure TForm1.OnPhongBorderSizeChange(Sender: TObject; AByUser: boolean);
+begin
+  FPhongBorderSize:= FUpDownPhongBorderSize.Value;
+  if AByUser and Assigned(vectorOriginal) and Assigned(vectorOriginal.SelectedShape) and
+    (vectorOriginal.SelectedShape is TPhongShape) then
+    TPhongShape(vectorOriginal.SelectedShape).BorderSizePercent:= FPhongBorderSize;
+end;
+
+procedure TForm1.OnPhongShapeAltitudeChange(Sender: TObject; AByUser: boolean);
+begin
+  FPhongShapeAltitude:= FUpDownPhongShapeAltitude.Value;
+  if AByUser and Assigned(vectorOriginal) and Assigned(vectorOriginal.SelectedShape) and
+    (vectorOriginal.SelectedShape is TPhongShape) then
+    TPhongShape(vectorOriginal.SelectedShape).ShapeAltitudePercent:= FPhongShapeAltitude;
+end;
+
 procedure TForm1.OnSelectShape(ASender: TObject; AShape: TVectorShape;
 procedure TForm1.OnSelectShape(ASender: TObject; AShape: TVectorShape;
   APreviousShape: TVectorShape);
   APreviousShape: TVectorShape);
 begin
 begin
@@ -1044,6 +1090,12 @@ begin
   backGradInterp := TBGRAColorInterpolation((ASender as TMenuItem).Tag);
   backGradInterp := TBGRAColorInterpolation((ASender as TMenuItem).Tag);
 end;
 end;
 
 
+procedure TForm1.PhongShapeKindClick(Sender: TObject);
+begin
+  if (Sender as TToolButton).Down then
+    phongShapeKind:= TPhongShapeKind((Sender as TToolButton).Tag);
+end;
+
 procedure TForm1.SetBackColor(AValue: TBGRAPixel);
 procedure TForm1.SetBackColor(AValue: TBGRAPixel);
 begin
 begin
   FBackColor := AValue;
   FBackColor := AValue;
@@ -1179,6 +1231,7 @@ begin
   ToolButtonClosedCurve.Down := FCurrentTool = ptClosedCurve;
   ToolButtonClosedCurve.Down := FCurrentTool = ptClosedCurve;
   ToolButtonPolyline.Down := FCurrentTool = ptPolyline;
   ToolButtonPolyline.Down := FCurrentTool = ptPolyline;
   ToolButtonCurve.Down := FCurrentTool = ptCurve;
   ToolButtonCurve.Down := FCurrentTool = ptCurve;
+  ToolButtonPhongShape.Down:= FCurrentTool = ptPhongShape;
   ButtonMoveBackFillPoints.Down := FCurrentTool = ptMoveBackFillPoint;
   ButtonMoveBackFillPoints.Down := FCurrentTool = ptMoveBackFillPoint;
   UpdateShapeUserMode;
   UpdateShapeUserMode;
 end;
 end;
@@ -1233,6 +1286,29 @@ begin
     vectorOriginal.SelectedShape.PenWidth:= penWidth;
     vectorOriginal.SelectedShape.PenWidth:= penWidth;
 end;
 end;
 
 
+procedure TForm1.SetPhongShapeKind(AValue: TPhongShapeKind);
+var
+  btn: TToolButton;
+  i: Integer;
+begin
+  if FPhongShapeKind=AValue then Exit;
+  FPhongShapeKind:=AValue;
+  if Assigned(FPhongShapeKindToolbar) then
+    for i := 0 to FPhongShapeKindToolbar.ButtonCount-1 do
+    begin
+      btn := FPhongShapeKindToolbar.Buttons[i];
+      if btn.Tag = ord(FPhongShapeKind) then btn.Down := true;
+    end;
+  if Assigned(FUpDownPhongBorderSize) then
+    FUpDownPhongBorderSize.Enabled:= (FPhongShapeKind = pskRoundRectangle);
+
+  if not FUpdatingFromShape and Assigned(vectorOriginal) and Assigned(vectorOriginal.SelectedShape) then
+  begin
+    if vectorOriginal.SelectedShape is TPhongShape then
+      TPhongShape(vectorOriginal.SelectedShape).ShapeKind:= FPhongShapeKind;
+  end;
+end;
+
 procedure TForm1.SetSplineStyle(AValue: TSplineStyle);
 procedure TForm1.SetSplineStyle(AValue: TSplineStyle);
 begin
 begin
   FSplineStyle := AValue;
   FSplineStyle := AValue;
@@ -1364,12 +1440,12 @@ procedure TForm1.UpdateToolbarFromShape(AShape: TVectorShape);
 const ControlMargin = 6;
 const ControlMargin = 6;
 var
 var
   f: TVectorShapeFields;
   f: TVectorShapeFields;
-  showSplineStyle: boolean;
+  showSplineStyle, showPhongStyle: boolean;
   nextControlPos: TPoint;
   nextControlPos: TPoint;
   s: TSplineStyle;
   s: TSplineStyle;
   texSource: TBGRABitmap;
   texSource: TBGRABitmap;
-  btn: TToolButton;
   mode: TVectorShapeUsermode;
   mode: TVectorShapeUsermode;
+  sk: TPhongShapeKind;
 begin
 begin
   RemoveExtendedStyleControls;
   RemoveExtendedStyleControls;
 
 
@@ -1421,6 +1497,16 @@ begin
       splineStyle:= TCurveShape(AShape).SplineStyle;
       splineStyle:= TCurveShape(AShape).SplineStyle;
     end else
     end else
       showSplineStyle:= false;
       showSplineStyle:= false;
+
+    if AShape is TPhongShape then
+    begin
+      showPhongStyle := true;
+      phongShapeKind:= TPhongShape(AShape).ShapeKind;
+      FPhongShapeAltitude:= TPhongShape(AShape).ShapeAltitudePercent;
+      FPhongBorderSize:= TPhongShape(AShape).BorderSizePercent;
+    end else
+      showPhongStyle := false;
+
     FUpdatingFromShape := false;
     FUpdatingFromShape := false;
   end else
   end else
   begin
   begin
@@ -1429,11 +1515,13 @@ begin
     begin
     begin
       f := PaintToolClass[currentTool].Fields;
       f := PaintToolClass[currentTool].Fields;
       showSplineStyle:= PaintToolClass[currentTool] = TCurveShape;
       showSplineStyle:= PaintToolClass[currentTool] = TCurveShape;
+      showPhongStyle := PaintToolClass[currentTool] = TPhongShape;
     end
     end
     else
     else
     begin
     begin
       f := [];
       f := [];
       showSplineStyle:= false;
       showSplineStyle:= false;
+      showPhongStyle:= false;
     end;
     end;
   end;
   end;
   UpdateBackComponentsVisibility;
   UpdateBackComponentsVisibility;
@@ -1444,15 +1532,10 @@ begin
   nextControlPos := Point(ControlMargin,4);
   nextControlPos := Point(ControlMargin,4);
   if showSplineStyle then
   if showSplineStyle then
   begin
   begin
-    FSplineToolbar := TToolBar.Create(nil);
-    FSplineToolbar.Align := alNone;
+    FSplineToolbar := CreateToolBar(CurveImageList);
     FSplineToolbar.Left := nextControlPos.X;
     FSplineToolbar.Left := nextControlPos.X;
     FSplineToolbar.Top := nextControlPos.Y;
     FSplineToolbar.Top := nextControlPos.Y;
-    FSplineToolbar.Height := 25;
     FSplineToolbar.Width := 120;
     FSplineToolbar.Width := 120;
-    FSplineToolbar.ShowHint:= true;
-    FSplineToolbar.ShowCaptions:= false;
-    FSplineToolbar.Images := CurveImageList;
     AddToolbarCheckButton(FSplineToolbar, 'Move spline points', 0, @SplineToolbarClick, mode in [vsuEdit, vsuCreate]);
     AddToolbarCheckButton(FSplineToolbar, 'Move spline points', 0, @SplineToolbarClick, mode in [vsuEdit, vsuCreate]);
     AddToolbarCheckButton(FSplineToolbar, 'Set to autodetect angle (A)', 1, @SplineToolbarClick, mode = vsuCurveSetAuto);
     AddToolbarCheckButton(FSplineToolbar, 'Set to autodetect angle (A)', 1, @SplineToolbarClick, mode = vsuCurveSetAuto);
     AddToolbarCheckButton(FSplineToolbar, 'Set to curve (S)', 2, @SplineToolbarClick, mode = vsuCurveSetCurve);
     AddToolbarCheckButton(FSplineToolbar, 'Set to curve (S)', 2, @SplineToolbarClick, mode = vsuCurveSetCurve);
@@ -1475,6 +1558,45 @@ begin
 
 
     nextControlPos.X := FComboboxSplineStyle.Left + FComboboxSplineStyle.Width + ControlMargin;
     nextControlPos.X := FComboboxSplineStyle.Left + FComboboxSplineStyle.Width + ControlMargin;
   end;
   end;
+  if showPhongStyle then
+  begin
+    FPhongShapeKindToolbar := CreateToolBar(PhongImageList);
+    FPhongShapeKindToolbar.Left := nextControlPos.X;
+    FPhongShapeKindToolbar.Top := nextControlPos.Y;
+    FPhongShapeKindToolbar.Width := 120;
+    for sk := low(TPhongShapeKind) to high(TPhongShapeKind) do
+      AddToolbarCheckButton(FPhongShapeKindToolbar, PhongShapeKindToStr[sk], ord(sk), @PhongShapeKindClick, FPhongShapeKind = sk, true, ord(sk));
+    PanelExtendedStyle.InsertControl(FPhongShapeKindToolbar);
+
+    FUpDownPhongShapeAltitude := TBCTrackbarUpdown.Create(nil);
+    FUpDownPhongShapeAltitude.Left := nextControlPos.X;
+    FUpDownPhongShapeAltitude.Top := nextControlPos.Y+FPhongShapeKindToolbar.Height;
+    FUpDownPhongShapeAltitude.Width := UpDownPenWidth.Width;
+    FUpDownPhongShapeAltitude.Height:= UpDownPenWidth.Height;
+    FUpDownPhongShapeAltitude.MinValue := 0;
+    FUpDownPhongShapeAltitude.MaxValue := 100;
+    FUpDownPhongShapeAltitude.Value := round(FPhongShapeAltitude);
+    FUpDownPhongShapeAltitude.Hint := 'Altitude';
+    FUpDownPhongShapeAltitude.ShowHint:= true;
+    FUpDownPhongShapeAltitude.OnChange:=@OnPhongShapeAltitudeChange;
+    PanelExtendedStyle.InsertControl(FUpDownPhongShapeAltitude);
+
+    FUpDownPhongBorderSize := TBCTrackbarUpdown.Create(nil);
+    FUpDownPhongBorderSize.Left := FUpDownPhongShapeAltitude.Left + FUpDownPhongShapeAltitude.Width + ControlMargin;
+    FUpDownPhongBorderSize.Top := nextControlPos.Y+FPhongShapeKindToolbar.Height;
+    FUpDownPhongBorderSize.Width := UpDownPenWidth.Width;
+    FUpDownPhongBorderSize.Height:= UpDownPenWidth.Height;
+    FUpDownPhongBorderSize.MinValue := 0;
+    FUpDownPhongBorderSize.MaxValue := 100;
+    FUpDownPhongBorderSize.Value := round(FPhongBorderSize);
+    FUpDownPhongBorderSize.Enabled:= (phongShapeKind in[pskRectangle,pskRoundRectangle]);
+    FUpDownPhongBorderSize.Hint := 'Border size';
+    FUpDownPhongBorderSize.ShowHint:= true;
+    FUpDownPhongBorderSize.OnChange:=@OnPhongBorderSizeChange;
+    PanelExtendedStyle.InsertControl(FUpDownPhongBorderSize);
+
+    nextControlPos.X := FPhongShapeKindToolbar.Left + FPhongShapeKindToolbar.Width + ControlMargin;
+  end;
 end;
 end;
 
 
 procedure TForm1.UpdateTitleBar;
 procedure TForm1.UpdateTitleBar;
@@ -1507,6 +1629,15 @@ begin
   if currentTool in[ptClosedCurve,ptPolygon] then
   if currentTool in[ptClosedCurve,ptPolygon] then
     TCustomPolypointShape(result).Closed := true;
     TCustomPolypointShape(result).Closed := true;
   if result is TCurveShape then TCurveShape(result).SplineStyle:= splineStyle;
   if result is TCurveShape then TCurveShape(result).SplineStyle:= splineStyle;
+  if result is TPhongShape then
+  begin
+    with TPhongShape(result) do
+    begin
+      ShapeKind:= FPhongShapeKind;
+      ShapeAltitudePercent:= FPhongShapeAltitude;
+      BorderSizePercent:= FPhongBorderSize;
+    end;
+  end;
   result.QuickDefine(APoint1,APoint2);
   result.QuickDefine(APoint1,APoint2);
   if vsfBackFill in result.Fields then
   if vsfBackFill in result.Fields then
   begin
   begin
@@ -1587,6 +1718,21 @@ begin
     PanelExtendedStyle.RemoveControl(FSplineToolbar);
     PanelExtendedStyle.RemoveControl(FSplineToolbar);
     FreeAndNil(FSplineToolbar);
     FreeAndNil(FSplineToolbar);
   end;
   end;
+  if Assigned(FPhongShapeKindToolbar) then
+  begin
+    PanelExtendedStyle.RemoveControl(FPhongShapeKindToolbar);
+    FreeAndNil(FPhongShapeKindToolbar);
+  end;
+  if Assigned(FUpDownPhongShapeAltitude) then
+  begin
+    PanelExtendedStyle.RemoveControl(FUpDownPhongShapeAltitude);
+    FreeAndNil(FUpDownPhongShapeAltitude);
+  end;
+  if Assigned(FUpDownPhongBorderSize) then
+  begin
+    PanelExtendedStyle.RemoveControl(FUpDownPhongBorderSize);
+    FreeAndNil(FUpDownPhongBorderSize);
+  end;
 end;
 end;
 
 
 procedure TForm1.UpdateBackComponentsVisibility;
 procedure TForm1.UpdateBackComponentsVisibility;

+ 380 - 8
vectoredit/uvectorshapes.pas

@@ -5,7 +5,8 @@ unit uvectorshapes;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, uvectororiginal, BGRABitmapTypes, BGRALayerOriginal, BGRABitmap, BGRATransform;
+  Classes, SysUtils, Types, uvectororiginal, BGRABitmapTypes, BGRALayerOriginal,
+  BGRABitmap, BGRATransform, BGRAGradients;
 
 
 type
 type
   { TCustomRectShape }
   { TCustomRectShape }
@@ -32,6 +33,7 @@ type
     function GetAffineBox(AMatrix: TAffineMatrix; APixelCentered: boolean): TAffineBox;
     function GetAffineBox(AMatrix: TAffineMatrix; APixelCentered: boolean): TAffineBox;
     function GetCornerPositition: single; virtual; abstract;
     function GetCornerPositition: single; virtual; abstract;
     function GetOrthoRect(AMatrix: TAffineMatrix; out ARect: TRectF): boolean;
     function GetOrthoRect(AMatrix: TAffineMatrix; out ARect: TRectF): boolean;
+    function AllowShearTransform: boolean; virtual;
   public
   public
     procedure QuickDefine(const APoint1,APoint2: TPointF); override;
     procedure QuickDefine(const APoint1,APoint2: TPointF); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
@@ -103,7 +105,7 @@ type
     function PointsEqual(const APoint1, APoint2: TPointF): boolean;
     function PointsEqual(const APoint1, APoint2: TPointF): boolean;
     procedure OnHoverPoint({%H-}ASender: TObject; APointIndex: integer); virtual;
     procedure OnHoverPoint({%H-}ASender: TObject; APointIndex: integer); virtual;
     procedure OnClickPoint({%H-}ASender: TObject; APointIndex: integer; {%H-}AShift: TShiftState); virtual;
     procedure OnClickPoint({%H-}ASender: TObject; APointIndex: integer; {%H-}AShift: TShiftState); virtual;
-    procedure DoClickPoint(APointIndex: integer; {%H-}AShift: TShiftState); virtual;
+    procedure DoClickPoint({%H-}APointIndex: integer; {%H-}AShift: TShiftState); virtual;
     function CanMovePoints: boolean; virtual;
     function CanMovePoints: boolean; virtual;
     procedure InsertPointAuto;
     procedure InsertPointAuto;
   public
   public
@@ -166,6 +168,49 @@ type
     property CurveMode[AIndex: integer]: TEasyBezierCurveMode read GetCurveMode write SetCurveMode;
     property CurveMode[AIndex: integer]: TEasyBezierCurveMode read GetCurveMode write SetCurveMode;
   end;
   end;
 
 
+  TPhongShapeKind = (pskRectangle, pskRoundRectangle, pskHalfSphere, pskConeTop, pskConeSide,
+                     pskHorizCylinder, pskVertCylinder);
+
+const
+  DefaultPhongShapeAltitudePercent = 20;
+  DefaultPhongBorderSizePercent = 20;
+
+type
+  { TPhongShape }
+
+  TPhongShape = class(TCustomRectShape)
+  private
+    FShapeKind: TPhongShapeKind;
+    FLightPosition: TPointF;
+    FShapeAltitudePercent: single;
+    FBorderSizePercent: single;
+    procedure OnMoveLightPos({%H-}ASender: TObject; {%H-}APrevCoord, ANewCoord: TPointF;
+      {%H-}AShift: TShiftState);
+    procedure SetBorderSizePercent(AValue: single);
+    procedure SetLightPosition(AValue: TPointF);
+    procedure SetShapeAltitudePercent(AValue: single);
+    procedure SetShapeKind(AValue: TPhongShapeKind);
+    function BackVisible: boolean;
+    function AllowShearTransform: boolean; override;
+  public
+    constructor Create(AContainer: TVectorOriginal); override;
+    destructor Destroy; override;
+    function GetCornerPositition: single; override;
+    class function Fields: TVectorShapeFields; override;
+    procedure ConfigureEditor(AEditor: TBGRAOriginalEditor); override;
+    procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
+    procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
+    procedure Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix; ADraft: boolean); override;
+    function GetRenderBounds({%H-}ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions = []): TRectF; override;
+    function PointInShape(APoint: TPointF): boolean; override;
+    function GetIsSlow(AMatrix: TAffineMatrix): boolean; override;
+    class function StorageClassName: RawByteString; override;
+    property ShapeKind: TPhongShapeKind read FShapeKind write SetShapeKind;
+    property LightPosition: TPointF read FLightPosition write SetLightPosition;
+    property ShapeAltitudePercent: single read FShapeAltitudePercent write SetShapeAltitudePercent;
+    property BorderSizePercent: single read FBorderSizePercent write SetBorderSizePercent;
+  end;
+
 implementation
 implementation
 
 
 uses BGRAPen, BGRAGraphics, BGRAFillInfo, BGRAPath, math;
 uses BGRAPen, BGRAGraphics, BGRAFillInfo, BGRAPath, math;
@@ -208,15 +253,22 @@ end;
 procedure TCustomRectShape.DoMoveXAxis(ANewCoord: TPointF; AShift: TShiftState; AFactor: single);
 procedure TCustomRectShape.DoMoveXAxis(ANewCoord: TPointF; AShift: TShiftState; AFactor: single);
 var
 var
   newSize: Single;
   newSize: Single;
+  u: TPointF;
 begin
 begin
   BeginUpdate;
   BeginUpdate;
-  if (ssAlt in AShift) or (FXUnitBackup = PointF(0,0)) then
+  if AllowShearTransform and ((ssAlt in AShift) or (FXUnitBackup = PointF(0,0))) then
   begin
   begin
     FXAxis := FOriginBackup + AFactor*(ANewCoord - FOriginBackup);
     FXAxis := FOriginBackup + AFactor*(ANewCoord - FOriginBackup);
     FYAxis := FYAxisBackup;
     FYAxis := FYAxisBackup;
     FOrigin := FOriginBackup;
     FOrigin := FOriginBackup;
-  end
-  else
+  end else
+  if FXUnitBackup = PointF(0,0) then
+  begin
+    u := ANewCoord - FOriginBackup;
+    FXAxis := FOriginBackup + u;
+    FYAxis := FOriginBackup + PointF(-u.y,u.x);
+    FOrigin := FOriginBackup;
+  end else
   begin
   begin
     newSize := AFactor*FXUnitBackup*(ANewCoord-FOriginBackup);
     newSize := AFactor*FXUnitBackup*(ANewCoord-FOriginBackup);
     if ssShift in AShift then
     if ssShift in AShift then
@@ -238,15 +290,22 @@ procedure TCustomRectShape.DoMoveYAxis(ANewCoord: TPointF; AShift: TShiftState;
   AFactor: single);
   AFactor: single);
 var
 var
   newSizeY: Single;
   newSizeY: Single;
+  u: TPointF;
 begin
 begin
   BeginUpdate;
   BeginUpdate;
-  if (ssAlt in AShift) or (FYUnitBackup = PointF(0,0)) then
+  if AllowShearTransform and ((ssAlt in AShift) or (FYUnitBackup = PointF(0,0))) then
   begin
   begin
     FYAxis := FOriginBackup + AFactor*(ANewCoord - FOriginBackup);
     FYAxis := FOriginBackup + AFactor*(ANewCoord - FOriginBackup);
     FXAxis := FXAxisBackup;
     FXAxis := FXAxisBackup;
     FOrigin := FOriginBackup;
     FOrigin := FOriginBackup;
-  end
-  else
+  end else
+  if FYUnitBackup = PointF(0,0) then
+  begin
+    u := ANewCoord - FOriginBackup;
+    FXAxis := FOriginBackup + PointF(u.y,-u.x);
+    FYAxis := FOriginBackup + u;
+    FOrigin := FOriginBackup;
+  end else
   begin
   begin
     newSizeY := AFactor*FYUnitBackup*(ANewCoord-FOriginBackup);
     newSizeY := AFactor*FYUnitBackup*(ANewCoord-FOriginBackup);
     if ssShift in AShift then
     if ssShift in AShift then
@@ -413,6 +472,11 @@ begin
   end;
   end;
 end;
 end;
 
 
+function TCustomRectShape.AllowShearTransform: boolean;
+begin
+  result := true;
+end;
+
 procedure TCustomRectShape.QuickDefine(const APoint1, APoint2: TPointF);
 procedure TCustomRectShape.QuickDefine(const APoint1, APoint2: TPointF);
 begin
 begin
   BeginUpdate;
   BeginUpdate;
@@ -1537,12 +1601,320 @@ begin
   Result:= 'curve';
   Result:= 'curve';
 end;
 end;
 
 
+{ TPhongShape }
+
+procedure TPhongShape.SetShapeKind(AValue: TPhongShapeKind);
+begin
+  if FShapeKind=AValue then Exit;
+  BeginUpdate;
+  FShapeKind:=AValue;
+  EndUpdate;
+end;
+
+procedure TPhongShape.OnMoveLightPos(ASender: TObject; APrevCoord,
+  ANewCoord: TPointF; AShift: TShiftState);
+begin
+  LightPosition := ANewCoord;
+end;
+
+procedure TPhongShape.SetBorderSizePercent(AValue: single);
+begin
+  if FBorderSizePercent=AValue then Exit;
+  BeginUpdate;
+  FBorderSizePercent:=AValue;
+  EndUpdate;
+end;
+
+procedure TPhongShape.SetLightPosition(AValue: TPointF);
+begin
+  if FLightPosition=AValue then Exit;
+  BeginUpdate;
+  FLightPosition:=AValue;
+  EndUpdate;
+end;
+
+procedure TPhongShape.SetShapeAltitudePercent(AValue: single);
+begin
+  if FShapeAltitudePercent=AValue then Exit;
+  BeginUpdate;
+  FShapeAltitudePercent:=AValue;
+  EndUpdate;
+end;
+
+function TPhongShape.BackVisible: boolean;
+begin
+  result := BackFill.IsGradient or BackFill.IsTexture or
+            (BackFill.IsSolid and (BackFill.SolidColor.alpha <> 0));
+end;
+
+function TPhongShape.AllowShearTransform: boolean;
+begin
+  Result:= false;
+end;
+
+constructor TPhongShape.Create(AContainer: TVectorOriginal);
+begin
+  inherited Create(AContainer);
+  FShapeKind:= pskRectangle;
+  FLightPosition := PointF(0,0);
+  FShapeAltitudePercent:= DefaultPhongShapeAltitudePercent;
+  FBorderSizePercent:= DefaultPhongBorderSizePercent;
+end;
+
+destructor TPhongShape.Destroy;
+begin
+  inherited Destroy;
+end;
+
+function TPhongShape.GetCornerPositition: single;
+begin
+  if ShapeKind in [pskHalfSphere,pskConeTop] then
+    result := sqrt(2)/2
+  else
+    result := 1;
+end;
+
+class function TPhongShape.Fields: TVectorShapeFields;
+begin
+  Result:= [vsfBackFill];
+end;
+
+procedure TPhongShape.ConfigureEditor(AEditor: TBGRAOriginalEditor);
+begin
+  inherited ConfigureEditor(AEditor);
+  AEditor.AddPoint(FLightPosition, @OnMoveLightPos, true);
+end;
+
+procedure TPhongShape.LoadFromStorage(AStorage: TBGRACustomOriginalStorage);
+begin
+  BeginUpdate;
+  inherited LoadFromStorage(AStorage);
+  LightPosition := AStorage.PointF['light-pos'];
+  if isEmptyPointF(LightPosition) then LightPosition := PointF(0,0);
+  case AStorage.RawString['shape-kind'] of
+    'round-rectangle': ShapeKind:= pskRoundRectangle;
+    'half-sphere': ShapeKind := pskHalfSphere;
+    'cone-top': ShapeKind := pskConeTop;
+    'cone-side': ShapeKind := pskConeSide;
+    'horizontal-cylinder': ShapeKind := pskHorizCylinder;
+    'vertical-cylinder': ShapeKind := pskVertCylinder;
+  else
+    {'rectangle'} ShapeKind:= pskRectangle;
+  end;
+  ShapeAltitudePercent := AStorage.FloatDef['shape-altitude-percent', DefaultPhongShapeAltitudePercent];
+  if ShapeKind = pskRoundRectangle then
+    BorderSizePercent := AStorage.FloatDef['border-size-percent', DefaultPhongBorderSizePercent]
+  else
+    BorderSizePercent := DefaultPhongBorderSizePercent;
+  EndUpdate;
+end;
+
+procedure TPhongShape.SaveToStorage(AStorage: TBGRACustomOriginalStorage);
+begin
+  inherited SaveToStorage(AStorage);
+  AStorage.PointF['light-pos'] := LightPosition;
+  case ShapeKind of
+    pskRectangle: AStorage.RawString['shape-kind'] := 'rectangle';
+    pskRoundRectangle: AStorage.RawString['shape-kind'] := 'round-rectangle';
+    pskHalfSphere: AStorage.RawString['shape-kind'] := 'half-sphere';
+    pskConeTop: AStorage.RawString['shape-kind'] := 'cone-top';
+    pskConeSide: AStorage.RawString['shape-kind'] := 'cone-side';
+    pskHorizCylinder: AStorage.RawString['shape-kind'] := 'horizontal-cylinder';
+    pskVertCylinder: AStorage.RawString['shape-kind'] := 'vertical-cylinder';
+  end;
+  AStorage.Float['shape-altitude-percent'] := ShapeAltitudePercent;
+  if ShapeKind = pskRoundRectangle then
+    AStorage.Float['border-size-percent'] := FBorderSizePercent;
+end;
+
+procedure TPhongShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
+  ADraft: boolean);
+var
+  ab,abRaster: TAffineBox;
+  mapWidth,mapHeight: integer;
+  shader: TPhongShading;
+  approxFactor,borderSize: single;
+  m: TAffineMatrix;
+  h: single;
+  map,raster: TBGRABitmap;
+  u,v,lightPosF: TPointF;
+  scan: TBGRACustomScanner;
+  rectRenderF,rectRasterF: TRectF;
+  rectRender,rectRaster, prevClip: TRect;
+begin
+  if not BackVisible then exit;
+
+  //determine final render bounds
+  rectRenderF := GetRenderBounds(InfiniteRect,AMatrix);
+  if IsEmptyRectF(rectRenderF) then exit;
+
+  rectRender := rect(floor(rectRenderF.Left),floor(rectRenderF.Top),ceil(rectRenderF.Right),ceil(rectRenderF.Bottom));
+  rectRender.Intersect(ADest.ClipRect);
+  if IsRectEmpty(rectRender) then exit;
+
+  //determine map size before transform
+  ab := GetAffineBox(AMatrix, false);
+  if ab.Width > ab.Height then
+  begin
+    if ab.Width = 0 then exit;
+    mapWidth := ceil(ab.Width);
+    mapHeight := ceil(ab.Surface/ab.Width);
+  end else
+  begin
+    mapWidth := ceil(ab.Surface/ab.Height);
+    mapHeight := ceil(ab.Height);
+  end;
+  approxFactor := 1;
+  if ADraft then
+  begin
+    if mapWidth > 300 then approxFactor:= min(approxFactor, 300/mapWidth);
+    if mapHeight > 300 then approxFactor:= min(approxFactor, 300/mapHeight);
+  end;
+  mapWidth:= ceil(mapWidth*approxFactor);
+  mapHeight:= ceil(mapHeight*approxFactor);
+
+  //determine map transform
+  u := (ab.TopRight-ab.TopLeft)*(1/ab.Width);
+  v := (ab.BottomLeft-ab.TopLeft)*(1/ab.Height);
+  m := AffineMatrix(u,v,ab.TopLeft)*AffineMatrixScale(ab.Width/mapWidth,ab.Height/mapHeight);
+  borderSize := FBorderSizePercent/200*min(ab.Width,ab.Height);
+
+  try
+    //create height map
+    map := nil;
+
+    case ShapeKind of
+      pskRoundRectangle: begin
+        map := CreateRoundRectanglePreciseMap(mapWidth,mapHeight,
+                      round(borderSize*mapWidth/ab.Width),
+                      round(borderSize*mapHeight/ab.Height),[]);
+        h := FShapeAltitudePercent*approxFactor;
+      end;
+      pskHalfSphere: begin
+        map := CreateSpherePreciseMap(mapWidth,mapHeight);
+        h := FShapeAltitudePercent/100*sqrt(mapWidth*mapHeight);
+      end;
+      pskConeTop: begin
+        map := CreateConePreciseMap(mapWidth,mapHeight);
+        h := FShapeAltitudePercent/100*sqrt(mapWidth*mapHeight);
+      end;
+      pskConeSide: begin
+        map := CreateVerticalConePreciseMap(mapWidth,mapHeight);
+        h := FShapeAltitudePercent/100*mapWidth;
+      end;
+      pskHorizCylinder: begin
+        map := CreateHorizontalCylinderPreciseMap(mapWidth,mapHeight);
+        h := FShapeAltitudePercent/100*mapHeight;
+      end;
+      pskVertCylinder: begin
+        map := CreateVerticalCylinderPreciseMap(mapWidth,mapHeight);
+        h := FShapeAltitudePercent/100*mapWidth;
+      end;
+    else
+      {pskRectangle: }begin
+        map := CreateRectanglePreciseMap(mapWidth,mapHeight,
+                      round(borderSize*mapWidth/ab.Width),
+                      round(borderSize*mapHeight/ab.Height),[]);
+        h := FShapeAltitudePercent*approxFactor;
+      end;
+    end;
+
+    abRaster := AffineMatrixInverse(m)*TAffineBox.AffineBox(rectRenderF);
+    rectRasterF := abRaster.RectBoundsF;
+    rectRaster := rect(floor(rectRasterF.Left),floor(rectRasterF.Top),ceil(rectRasterF.Right),ceil(rectRasterF.Bottom));
+
+    raster := nil;
+    shader := nil;
+    if IntersectRect(rectRaster, rectRaster, rect(0,0,mapWidth,mapHeight)) then
+    try
+      shader:= TPhongShading.Create;
+      lightPosF := AffineMatrixTranslation(-rectRaster.Left,-rectRaster.Top)
+                    *AffineMatrixInverse(m)*AMatrix
+                    *PointF(FLightPosition.x,FLightPosition.y);
+      shader.LightPosition := Point(round(lightPosF.x),round(lightPosF.y));
+      shader.LightPositionZ := round(100*power(approxFactor,1.18));
+      if h*3/2 > shader.LightPositionZ then
+       shader.LightPositionZ := round(h*3/2);
+
+      raster := TBGRABitmap.Create(rectRaster.Width,rectRaster.Height);
+      if BackFill.IsSolid then
+        shader.Draw(raster,map,round(h),-rectRaster.Left,-rectRaster.Top,BackFill.SolidColor)
+      else
+      begin
+        scan := BackFill.CreateScanner(AffineMatrixTranslation(-rectRaster.left,-rectRaster.top)*AffineMatrixInverse(m)*AMatrix,ADraft);
+        shader.DrawScan(raster,map,round(h),-rectRaster.Left,-rectRaster.Top,scan);
+        scan.Free;
+      end;
+
+      prevClip := ADest.ClipRect;
+      ADest.ClipRect := rectRender;
+      if ADraft then
+        ADest.PutImageAffine(m*AffineMatrixTranslation(rectRaster.Left,rectRaster.Top),raster,rfBox,dmDrawWithTransparency)
+      else
+        ADest.PutImageAffine(m*AffineMatrixTranslation(rectRaster.Left,rectRaster.Top),raster,rfHalfCosine,dmDrawWithTransparency);
+      ADest.ClipRect := prevClip;
+
+    finally
+      raster.Free;
+      shader.Free;
+    end;
+  finally
+    map.Free;
+  end;
+end;
+
+function TPhongShape.GetRenderBounds(ADestRect: TRect; AMatrix: TAffineMatrix;
+  AOptions: TRenderBoundsOptions): TRectF;
+begin
+  if not (BackVisible or (rboAssumeBackFill in AOptions)) then
+    result:= EmptyRectF
+  else
+    result := inherited GetRenderBounds(ADestRect, AMatrix, AOptions);
+end;
+
+function TPhongShape.PointInShape(APoint: TPointF): boolean;
+var
+  box: TAffineBox;
+  pts: ArrayOfTPointF;
+begin
+  if not BackVisible then exit(false);
+  if ShapeKind in [pskHalfSphere, pskConeTop] then
+  begin
+    pts := ComputeEllipse(FOrigin, FXAxis, FYAxis);
+    result := IsPointInPolygon(pts, APoint, true);
+  end else
+  if ShapeKind = pskConeSide then
+  begin
+    pts:= PointsF([FOrigin - (FYAxis-FOrigin), FYAxis + (FXAxis-FOrigin), FYAxis - (FXAxis-FOrigin)]);
+    result := IsPointInPolygon(pts, APoint, true);
+  end else
+  begin
+    box := GetAffineBox(AffineMatrixIdentity, true);
+    result:= box.Contains(APoint);
+  end;
+end;
+
+function TPhongShape.GetIsSlow(AMatrix: TAffineMatrix): boolean;
+var
+  ab: TAffineBox;
+begin
+  if not BackVisible then exit(false);
+  ab := GetAffineBox(AMatrix, true);
+  result := ab.Surface > 320*240;
+end;
+
+class function TPhongShape.StorageClassName: RawByteString;
+begin
+  result := 'phong';
+end;
+
 initialization
 initialization
 
 
   RegisterVectorShape(TRectShape);
   RegisterVectorShape(TRectShape);
   RegisterVectorShape(TEllipseShape);
   RegisterVectorShape(TEllipseShape);
   RegisterVectorShape(TPolylineShape);
   RegisterVectorShape(TPolylineShape);
   RegisterVectorShape(TCurveShape);
   RegisterVectorShape(TCurveShape);
+  RegisterVectorShape(TPhongShape);
 
 
 end.
 end.