├── .gitignore ├── BeautifulDialog ├── BeautifulDialog.fmx ├── BeautifulDialog.pas ├── BeautyDlgDemo.dpr └── BeautyDlgDemo.dproj ├── CameraPerformance ├── .gitignore ├── AndroidManifest.template.xml ├── CameraPerformance.deployproj ├── CameraPerformance.dpr ├── CameraPerformance.dproj ├── Custom │ ├── FMX.Media.AVFoundation.pas │ └── FMX.Media.Android.pas ├── Entitlement.TemplateiOS.xml ├── FMain.NmXhdpiPh.fmx ├── FMain.Windows.fmx ├── FMain.fmx ├── FMain.iPhone4in.fmx ├── FMain.pas ├── Fast │ └── FastUtils.pas └── SIMD │ ├── FastUtils.pas │ ├── libfastutils-android.a │ └── libfastutils.a ├── DonationList.md ├── FMXPrint ├── FMXPrintDemo.dpr ├── FMXPrintDemo.dproj ├── PrintDemoMain.fmx └── PrintDemoMain.pas ├── Gif2PngDemo ├── Gif2PngDemo.dpr ├── Gif2PngDemo.dproj ├── Gif2PngDemo.res ├── Gif2PngDemo.stat ├── GifDemoMain.dfm ├── GifDemoMain.pas ├── Test.gif └── Test.png ├── HtmlParserTest ├── HtmlParserTest.dpr ├── HtmlParserTest.dproj ├── HtmlParserTestMain.dfm ├── HtmlParserTestMain.pas ├── README.md ├── Test.html └── htmlp │ ├── DOMCore.pas │ ├── Entities.pas │ ├── Formatter.pas │ ├── HTMLParser.pas │ ├── HtmlReader.pas │ ├── HtmlTags.pas │ └── WStrings.pas ├── HtmlParserTest_D7 ├── HtmlParserTest.cfg ├── HtmlParserTest.dof ├── HtmlParserTest.dpr ├── HtmlParserTest.dproj ├── HtmlParserTest.res ├── HtmlParserTestMain.dfm ├── HtmlParserTestMain.pas ├── README.md ├── Test.html └── htmlp │ ├── DOMCore.pas │ ├── Entities.pas │ ├── Formatter.pas │ ├── HTMLParser.pas │ ├── HtmlReader.pas │ ├── HtmlTags.pas │ └── WStrings.pas ├── LoadCustomCursor ├── CursorTest.dfm ├── CursorTest.pas ├── LoadCustomCursor.dpr ├── LoadCustomCursor.dproj └── Move.cur ├── README.md ├── Recorder ├── RecorderDemo.dpr ├── RecorderDemo.dproj ├── RecorderDemo.dproj.local ├── RecorderDemo.res ├── RecorderDemoMain.fmx └── RecorderDemoMain.pas ├── RoundImageDemo ├── DemoImage.png ├── RoundImageDemo.dpr ├── RoundImageDemo.dproj ├── RoundImageDemo.res ├── RoundImageForm.fmx └── RoundImageForm.pas ├── ScanCodeDemo ├── AndroidManifest.template.xml ├── CameraConfigurationUtils.pas ├── Custom │ ├── Androidapi.JNI.Embarcadero.pas │ ├── Androidapi.JNI.Hardware.pas │ ├── Androidapi.JNI.Media.pas │ ├── FMX.Media.AVFoundation.pas │ └── FMX.Media.Android.pas ├── Entitlement.TemplateiOS.xml ├── Fast │ └── FastUtils.pas ├── QMScanCode.fmx ├── QMScanCode.pas ├── SIMD │ ├── FastUtils.pas │ ├── libfastutils-android.a │ └── libfastutils.a ├── ScanCodeDemo.deployproj ├── ScanCodeDemo.dpr ├── ScanCodeDemo.dproj ├── readme.md └── res │ └── raw │ └── beep.ogg ├── TestButton ├── Main.fmx ├── Main.pas ├── TestButton.dpr └── TestButton.dproj ├── Tools ├── ResConvert.bdsproj ├── ResConvert.cfg ├── ResConvert.dpr ├── ResConvertMain.dfm └── ResConvertMain.pas └── ZXingScanDemo ├── AndroidManifest.template.xml ├── CameraConfigurationUtils.pas ├── ZXingScanDemo.deployproj ├── ZXingScanDemo.dpr ├── ZXingScanDemo.dproj ├── ZXingScanDemo.res ├── ZXingScanDemo.stat ├── main.LgXhdpiPh.fmx ├── main.NmXhdpiPh.fmx ├── main.fmx ├── main.iPhone55in.fmx └── main.pas /.gitignore: -------------------------------------------------------------------------------- 1 | /HtmlParserTest/Win32 2 | /HtmlParserTest/__history 3 | /HtmlParserTest/HtmlParserTest.dproj.local 4 | /HtmlParserTest/htmlp/__history 5 | /HtmlParserTest/*.identcache 6 | /HtmlParserTest/HtmlParserTest.res 7 | /HtmlParserTest_D7/htmlp/*.dcu 8 | /FMXPrint/Win32/Debug 9 | /FMXPrint/Win64/Debug 10 | /FMXPrint/__history 11 | /FMXPrint/FMXPrintDemo.dproj.local 12 | /FMXPrint/FMXPrintDemo.identcache 13 | /FMXPrint/FMXPrintDemo.res 14 | /BeautifulDialog/__history 15 | /BeautifulDialog/BeautyDlgDemo.dproj.local 16 | /BeautifulDialog/BeautyDlgDemo.res 17 | /BeautifulDialog/Win32/Debug 18 | /BeautifulDialog/BeautyDlgDemo.identcache 19 | /BeautifulDialog/BeautyDlgDemo.stat 20 | /TestButton/__history 21 | /TestButton/Win32/Debug 22 | /FMXPrint/*.stat 23 | /TestButton/*.res 24 | /LoadCustomCursor/Debug/Win32 25 | /LoadCustomCursor/__history 26 | /TestButton/*.local 27 | /TestButton/*.identcache 28 | /TestButton/*.stat 29 | /LoadCustomCursor/LoadCustomCursorResource.rc 30 | /LoadCustomCursor/LoadCustomCursor.dproj.local 31 | /LoadCustomCursor/LoadCustomCursor.dres 32 | /LoadCustomCursor/LoadCustomCursor.identcache 33 | /LoadCustomCursor/LoadCustomCursor.res 34 | /LoadCustomCursor/LoadCustomCursor.stat 35 | /ZXingScanDemo/__history 36 | /ZXingScanDemo/ZXingScanDemo.dproj.local 37 | /ZXingScanDemo/ZXingScanDemo.identcache 38 | /GifDemo/__history 39 | /GifDemo/Win32/Debug 40 | /Gif2PngDemo/__history 41 | /Recorder/Win32/Debug 42 | /Recorder/__history 43 | /Gif2PngDemo/Gif2PngDemo.dproj.local 44 | /Gif2PngDemo/Gif2PngDemo.identcache 45 | /Gif2PngDemo/Win32/Debug 46 | /Gif2PngDemo/Win32/Release 47 | /ZXingScanDemo/Android/Debug 48 | /ZXingScanDemo/Win32/Debug 49 | /CameraPerformance/__history 50 | /RoundImageDemo/Win32/Debug 51 | /RoundImageDemo/__history 52 | /RoundImageDemo/RoundImageDemo.dproj.local 53 | /CameraPerformance/Android/Release-SIMD 54 | 55 | /ScanCodeDemo/Android/Release-SIMD 56 | /ScanCodeDemo/CameraPerformance.identcache 57 | /ScanCodeDemo/CameraPerformance.res 58 | /ScanCodeDemo/CameraPerformance.stat 59 | /ScanCodeDemo/Custom/__history 60 | /ScanCodeDemo/__history 61 | /ScanCodeDemo/ScanCodeDemo.dproj.local 62 | /ScanCodeDemo/ScanCodeDemo.identcache 63 | /ScanCodeDemo/ScanCodeDemo.res 64 | /ScanCodeDemo/ScanCodeDemo.stat 65 | -------------------------------------------------------------------------------- /BeautifulDialog/BeautifulDialog.fmx: -------------------------------------------------------------------------------- 1 | object Form19: TForm19 2 | Left = 0 3 | Top = 0 4 | BorderStyle = None 5 | Caption = 'Form19' 6 | ClientHeight = 148 7 | ClientWidth = 328 8 | StyleBook = stylbk1 9 | StyleLookup = 'dialog-box' 10 | FormFactor.Width = 320 11 | FormFactor.Height = 480 12 | FormFactor.Devices = [Desktop] 13 | DesignerMasterStyle = 0 14 | object Layout1: TLayout 15 | Align = Bottom 16 | Margins.Bottom = 23.000000000000000000 17 | Position.Y = 103.000000000000000000 18 | Size.Width = 328.000000000000000000 19 | Size.Height = 22.000000000000000000 20 | Size.PlatformDefault = False 21 | TabOrder = 1 22 | object btn1: TButton 23 | Align = Center 24 | Margins.Left = 10.000000000000000000 25 | Margins.Top = 10.000000000000000000 26 | Margins.Right = 10.000000000000000000 27 | Margins.Bottom = 10.000000000000000000 28 | Size.Width = 70.000000000000000000 29 | Size.Height = 22.000000000000000000 30 | Size.PlatformDefault = False 31 | StyleLookup = 'a.button' 32 | TabOrder = 0 33 | Text = 'Close' 34 | OnClick = btn1Click 35 | end 36 | end 37 | object Layout2: TLayout 38 | Align = Client 39 | Size.Width = 328.000000000000000000 40 | Size.Height = 103.000000000000000000 41 | Size.PlatformDefault = False 42 | TabOrder = 2 43 | object txt1: TText 44 | StyleName = 'dialog.message' 45 | Align = Contents 46 | Padding.Left = 10.000000000000000000 47 | Padding.Top = 10.000000000000000000 48 | Padding.Right = 10.000000000000000000 49 | Padding.Bottom = 10.000000000000000000 50 | Margins.Left = 13.000000000000000000 51 | Margins.Top = 13.000000000000000000 52 | Margins.Right = 13.000000000000000000 53 | Margins.Bottom = 13.000000000000000000 54 | Size.Width = 302.000000000000000000 55 | Size.Height = 77.000000000000000000 56 | Size.PlatformDefault = False 57 | Text = 58 | 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi ' + 59 | 'commodo, ipsum sed pharetra gravida, orci magna rhoncus neque, i' + 60 | 'd pulvinar odio lorem non turpis. Nullam sit amet enim. Suspendi' + 61 | 'sse id velit vitae ligula volutpat condimentum. Aliquam erat vol' + 62 | 'utpat.' 63 | TextSettings.Font.Size = 11.000000000000000000 64 | TextSettings.FontColor = xFF666666 65 | TextSettings.HorzAlign = Leading 66 | TextSettings.VertAlign = Leading 67 | end 68 | end 69 | object stylbk1: TStyleBook 70 | Styles = < 71 | item 72 | ResourcesBin = { 73 | 464D585F5354594C4520322E3501060A6469616C6F672D626F78031901060861 74 | 2E627574746F6E03FA05060E6469616C6F672E6D65737361676503D800005450 75 | 46300C545374796C654F626A65637400095374796C654E616D65060A6469616C 76 | 6F672D626F780A506F736974696F6E2E580500000000000000E507400A506F73 77 | 6974696F6E2E5905000000000000008D07400756697369626C65080A536F7572 78 | 63654C696E6B0E00000A5452656374616E676C6500095374796C654E616D6506 79 | 0F72656374616E676C65317374796C6505416C69676E0708436F6E74656E7473 80 | 0A46696C6C2E436F6C6F7207097846464545454545450748697454657374080A 81 | 53697A652E57696474680500000000000000C804400B53697A652E4865696768 82 | 740500000000000000C804401453697A652E506C6174666F726D44656661756C 83 | 74080B5374726F6B652E4B696E6407044E6F6E650000005450463007544C6179 84 | 6F757400095374796C654E616D650608612E627574746F6E0A506F736974696F 85 | 6E2E580500000000000000E307400A506F736974696F6E2E5905000000000000 86 | 00FD06400A53697A652E576964746805000000000000008C05400B53697A652E 87 | 4865696768740500000000000000B003401453697A652E506C6174666F726D44 88 | 656661756C7408085461624F726465720201000A5452656374616E676C650009 89 | 5374796C654E616D65060A6261636B67726F756E6405416C69676E0708436F6E 90 | 74656E74730A46696C6C2E436F6C6F7207097846464533333130300748697454 91 | 657374080553696465730B06426F74746F6D000A53697A652E57696474680500 92 | 0000000000008C05400B53697A652E4865696768740500000000000000B00340 93 | 1453697A652E506C6174666F726D44656661756C74080C5374726F6B652E436F 94 | 6C6F720709783430303030303030000F54436F6C6F72416E696D6174696F6E00 95 | 095374796C654E616D650614636F6C6F72616E696D6174696F6E317374796C65 96 | 084475726174696F6E050000000000CDCCCCFC3F0C50726F70657274794E616D 97 | 65060A46696C6C2E436F6C6F720A537461727456616C75650709784646453333 98 | 3130300953746F7056616C756507097846464333333130300754726967676572 99 | 061049734D6F7573654F7665723D747275650E54726967676572496E76657273 100 | 65061149734D6F7573654F7665723D66616C73650000000654476C7970680009 101 | 5374796C654E616D65060A676C7970687374796C650C4D617267696E732E4C65 102 | 66740500000000000000C000400B4D617267696E732E546F7005000000000000 103 | 008000400D4D617267696E732E5269676874050000000000000080FF3F0E4D61 104 | 7267696E732E426F74746F6D050000000000000080004005416C69676E07044C 105 | 6566740A53697A652E576964746805000000000000008003400B53697A652E48 106 | 656967687405000000000000008003401453697A652E506C6174666F726D4465 107 | 6661756C740800001654427574746F6E5374796C65546578744F626A65637400 108 | 095374796C654E616D6506047465787405416C69676E070643656E746572064C 109 | 6F636B6564090C4D617267696E732E4C656674050000000000000080FF3F0B4D 110 | 617267696E732E546F7005000000000000008000400D4D617267696E732E5269 111 | 676874050000000000000080FF3F0E4D617267696E732E426F74746F6D050000 112 | 00000000008000400A53697A652E576964746805000000000000009C05400B53 113 | 697A652E48656967687405000000000000009003401453697A652E506C617466 114 | 6F726D44656661756C7408175465787453657474696E67732E466F6E742E5374 115 | 796C650B066673426F6C6400165465787453657474696E67732E466F6E74436F 116 | 6C6F720708636C6157686974650C536861646F772E436F6C6F72070978343030 117 | 303030303010536861646F772E4F66667365742E584902FF10536861646F772E 118 | 4F66667365742E594902010D536861646F7756697369626C650908486F74436F 119 | 6C6F720708636C6157686974650F486F74536861646F772E436F6C6F72070978 120 | 343030303030303013486F74536861646F772E4F66667365742E584902FF1348 121 | 6F74536861646F772E4F66667365742E594902010C466F6375736564436F6C6F 122 | 720708636C61576869746513466F6375736564536861646F772E436F6C6F7207 123 | 0978343030303030303017466F6375736564536861646F772E4F66667365742E 124 | 584902FF17466F6375736564536861646F772E4F66667365742E594902010B4E 125 | 6F726D616C436F6C6F720708636C615768697465124E6F726D616C536861646F 126 | 772E436F6C6F720709783430303030303030164E6F726D616C536861646F772E 127 | 4F66667365742E584902FF164E6F726D616C536861646F772E4F66667365742E 128 | 594902010C50726573736564436F6C6F720708636C6157686974651350726573 129 | 736564536861646F772E436F6C6F720709783430303030303030175072657373 130 | 6564536861646F772E4F66667365742E584902FF175072657373656453686164 131 | 6F772E4F66667365742E594902010000005450463010545374796C6554657874 132 | 4F626A65637400095374796C654E616D65060E6469616C6F672E6D6573736167 133 | 650A506F736974696F6E2E580500000000000000E507400A506F736974696F6E 134 | 2E5905000000000000008D0740165465787453657474696E67732E466F6E7443 135 | 6F6C6F720709784646363636363636165465787453657474696E67732E486F72 136 | 7A416C69676E07074C656164696E67165465787453657474696E67732E566572 137 | 74416C69676E07074C656164696E670756697369626C65080D536861646F7756 138 | 697369626C65080000} 139 | end> 140 | Left = 200 141 | Top = 88 142 | end 143 | end 144 | -------------------------------------------------------------------------------- /BeautifulDialog/BeautifulDialog.pas: -------------------------------------------------------------------------------- 1 | unit BeautifulDialog; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts, 8 | FMX.Controls.Presentation, FMX.StdCtrls, FMX.Objects, FMX.Effects; 9 | 10 | type 11 | TForm19 = class(TForm) 12 | stylbk1: TStyleBook; 13 | Layout1: TLayout; 14 | btn1: TButton; 15 | txt1: TText; 16 | Layout2: TLayout; 17 | procedure btn1Click(Sender: TObject); 18 | procedure btn2Click(Sender: TObject); 19 | private 20 | { Private declarations } 21 | public 22 | { Public declarations } 23 | end; 24 | 25 | var 26 | Form19: TForm19; 27 | 28 | implementation 29 | 30 | {$R *.fmx} 31 | 32 | procedure TForm19.btn1Click(Sender: TObject); 33 | begin 34 | Close; 35 | end; 36 | 37 | procedure TForm19.btn2Click(Sender: TObject); 38 | begin 39 | Close; 40 | end; 41 | 42 | end. 43 | -------------------------------------------------------------------------------- /BeautifulDialog/BeautyDlgDemo.dpr: -------------------------------------------------------------------------------- 1 | program BeautyDlgDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | BeautifulDialog in 'BeautifulDialog.pas' {Form19}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm19, Form19); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /CameraPerformance/.gitignore: -------------------------------------------------------------------------------- 1 | /Android 2 | /CameraPerformance.dproj.local 3 | /CameraPerformance.identcache 4 | /CameraPerformance.res 5 | /CameraPerformance.stat 6 | -------------------------------------------------------------------------------- /CameraPerformance/AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | <%uses-permission%> 12 | 13 | 21 | 22 | <%application-meta-data%> 23 | 25 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | <%activity%> 38 | 39 | <%receivers%> 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /CameraPerformance/CameraPerformance.dpr: -------------------------------------------------------------------------------- 1 | program CameraPerformance; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | FMain in 'FMain.pas' {FormMain}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TFormMain, FormMain); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /CameraPerformance/Entitlement.TemplateiOS.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%getTaskAllowKey%> 6 | <%applicationIdentifier%> 7 | <%pushNotificationKey%> 8 | <%keychainAccessGroups%> 9 | 10 | 11 | -------------------------------------------------------------------------------- /CameraPerformance/FMain.fmx: -------------------------------------------------------------------------------- 1 | object FormMain: TFormMain 2 | Left = 0 3 | Top = 0 4 | Caption = 'Camera Performance' 5 | ClientHeight = 480 6 | ClientWidth = 320 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnCreate = FormCreate 11 | OnDestroy = FormDestroy 12 | DesignerMasterStyle = 0 13 | object ToolBar: TToolBar 14 | Padding.Left = 8.000000000000000000 15 | Padding.Right = 8.000000000000000000 16 | Size.Width = 320.000000000000000000 17 | Size.Height = 48.000000000000000000 18 | Size.PlatformDefault = False 19 | TabOrder = 0 20 | object ButtonSwitchCamera: TButton 21 | Align = Right 22 | Images = ImageList 23 | ImageIndex = 0 24 | Margins.Left = 8.000000000000000000 25 | Position.X = 268.000000000000000000 26 | Size.Width = 44.000000000000000000 27 | Size.Height = 48.000000000000000000 28 | Size.PlatformDefault = False 29 | StyleLookup = 'toolbutton' 30 | TabOrder = 0 31 | OnClick = ButtonSwitchCameraClick 32 | end 33 | object LayoutSetting: TLayout 34 | Align = Client 35 | Size.Width = 175.000000000000000000 36 | Size.Height = 48.000000000000000000 37 | Size.PlatformDefault = False 38 | TabOrder = 1 39 | object PopupBoxSetting: TPopupBox 40 | Align = VertCenter 41 | Position.Y = 8.000000000000000000 42 | Size.Width = 175.000000000000000000 43 | Size.Height = 32.000000000000000000 44 | Size.PlatformDefault = False 45 | TabOrder = 0 46 | OnChange = PopupBoxSettingChange 47 | end 48 | end 49 | object LabelSetting: TLabel 50 | Align = Left 51 | HitTest = True 52 | Position.X = 8.000000000000000000 53 | Size.Width = 77.000000000000000000 54 | Size.Height = 48.000000000000000000 55 | Size.PlatformDefault = False 56 | StyleLookup = 'toollabel' 57 | Text = 'Setting' 58 | end 59 | end 60 | object StatusBar: TStatusBar 61 | Padding.Left = 8.000000000000000000 62 | Padding.Right = 8.000000000000000000 63 | Position.Y = 458.000000000000000000 64 | ShowSizeGrip = True 65 | Size.Width = 320.000000000000000000 66 | Size.Height = 22.000000000000000000 67 | Size.PlatformDefault = False 68 | TabOrder = 2 69 | object LabelFPS: TLabel 70 | Align = Client 71 | Size.Width = 304.000000000000000000 72 | Size.Height = 22.000000000000000000 73 | Size.PlatformDefault = False 74 | end 75 | end 76 | object PaintBox: TPaintBox 77 | Align = Client 78 | Size.Width = 320.000000000000000000 79 | Size.Height = 391.000000000000000000 80 | Size.PlatformDefault = False 81 | OnPaint = PaintBoxPaint 82 | end 83 | object CheckBoxDisplay: TCheckBox 84 | Align = Top 85 | IsChecked = True 86 | Margins.Left = 8.000000000000000000 87 | Position.X = 8.000000000000000000 88 | Position.Y = 48.000000000000000000 89 | Size.Width = 312.000000000000000000 90 | Size.Height = 19.000000000000000000 91 | Size.PlatformDefault = False 92 | TabOrder = 4 93 | Text = 'Display' 94 | OnChange = CheckBoxDisplayChange 95 | end 96 | object CameraComponent: TCameraComponent 97 | Kind = FrontCamera 98 | OnSampleBufferReady = CameraComponentSampleBufferReady 99 | Left = 156 100 | Top = 112 101 | end 102 | object ImageList: TImageList 103 | Source = <> 104 | Destination = <> 105 | Left = 60 106 | Top = 112 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /CameraPerformance/FMain.pas: -------------------------------------------------------------------------------- 1 | unit FMain; 2 | 3 | { 32-bit iPad 3 64-bit iPad 3 4 | "Normal" "Fast" "SIMD" "Normal" "Fast" "SIMD" 5 | 1080 x 1920 13.97 26.66 30.00 15.81 28.91 30.00 6 | +Display 10.96 17.68 26.53 12.30 18.67 27.00 7 | 1936 x 2592 6.03 11.81 24.11 6.73 12.37 24.02 8 | +Display 4.76 7.61 12.97 5.24 8.18 14.02 9 | 10 | Android TF300 11 | "Normal" "Fast" "SIMD" 12 | 480 x 640 5.40 15.44 16.70 13 | +Display 5.23 15.10 16.66 14 | 960 x 1280 1.61 3.87 13.69 15 | +Display 1.72 3.85 9.00 16 | } 17 | 18 | interface 19 | 20 | uses 21 | System.SysUtils, 22 | System.Types, 23 | System.UITypes, 24 | System.Classes, 25 | System.Variants, 26 | System.ImageList, 27 | System.Diagnostics, 28 | FMX.Types, 29 | FMX.Controls, 30 | FMX.Forms, 31 | FMX.Graphics, 32 | FMX.Dialogs, 33 | FMX.StdCtrls, 34 | FMX.ExtCtrls, 35 | FMX.Controls.Presentation, 36 | FMX.Media, 37 | FMX.ImgList, 38 | FMX.Layouts, 39 | FMX.Objects; 40 | 41 | type 42 | TFormMain = class(TForm) 43 | ToolBar: TToolBar; 44 | PopupBoxSetting: TPopupBox; 45 | ButtonSwitchCamera: TButton; 46 | ImageList: TImageList; 47 | LayoutSetting: TLayout; 48 | CheckBoxDisplay: TCheckBox; 49 | StatusBar: TStatusBar; 50 | LabelFPS: TLabel; 51 | PaintBox: TPaintBox; 52 | LabelSetting: TLabel; 53 | CameraComponent: TCameraComponent; 54 | procedure FormCreate(Sender: TObject); 55 | procedure FormDestroy(Sender: TObject); 56 | procedure PaintBoxPaint(Sender: TObject; Canvas: TCanvas); 57 | procedure ButtonSwitchCameraClick(Sender: TObject); 58 | procedure PopupBoxSettingChange(Sender: TObject); 59 | procedure CheckBoxDisplayChange(Sender: TObject); 60 | procedure CameraComponentSampleBufferReady(Sender: TObject; 61 | const ATime: TMediaTime); 62 | private 63 | { Private declarations } 64 | FCaptureSettings: TArray; 65 | FBitmap: TBitmap; 66 | FStopwatch: TStopwatch; 67 | FFrameCount: Integer; 68 | FUpdating: Boolean; 69 | procedure UpdateCaptureSettings; 70 | procedure ResetCapture; 71 | public 72 | { Public declarations } 73 | end; 74 | 75 | var 76 | FormMain: TFormMain; 77 | 78 | implementation 79 | 80 | {$R *.fmx} 81 | {$R *.iPhone4in.fmx IOS} 82 | {$R *.Windows.fmx MSWINDOWS} 83 | {$R *.NmXhdpiPh.fmx ANDROID} 84 | 85 | uses 86 | System.Generics.Collections, 87 | System.Generics.Defaults; 88 | 89 | procedure TFormMain.ButtonSwitchCameraClick(Sender: TObject); 90 | begin 91 | if (CameraComponent.Kind = TCameraKind.FrontCamera) then 92 | CameraComponent.Kind := TCameraKind.BackCamera 93 | else 94 | CameraComponent.Kind := TCameraKind.FrontCamera; 95 | 96 | UpdateCaptureSettings; 97 | ResetCapture; 98 | end; 99 | 100 | procedure TFormMain.CameraComponentSampleBufferReady(Sender: TObject; 101 | const ATime: TMediaTime); 102 | var 103 | Sec: Double; 104 | begin 105 | CameraComponent.SampleBufferToBitmap(FBitmap, True); 106 | 107 | if (CheckBoxDisplay.IsChecked) then 108 | PaintBox.Repaint; 109 | 110 | Sec := FStopwatch.Elapsed.TotalSeconds; 111 | 112 | { Ignore the first 3 seconds to get up to speed } 113 | if (Sec > 3) then 114 | begin 115 | Sec := Sec - 3; 116 | Inc(FFrameCount); 117 | LabelFPS.Text := Format('%.2f fps (%d x %d)', [FFrameCount / Sec, FBitmap.Width, FBitmap.Height]); 118 | end; 119 | end; 120 | 121 | procedure TFormMain.CheckBoxDisplayChange(Sender: TObject); 122 | begin 123 | ResetCapture; 124 | end; 125 | 126 | procedure TFormMain.FormCreate(Sender: TObject); 127 | begin 128 | ToolBar.Height := ToolBar.DefaultSize.Height; 129 | CheckBoxDisplay.Height := CheckBoxDisplay.DefaultSize.Height * 2; 130 | PopupBoxSetting.Height := PopupBoxSetting.DefaultSize.Height; 131 | 132 | FBitmap := TBitmap.Create; 133 | CameraComponent.Quality := TVideoCaptureQuality.CaptureSettings; 134 | UpdateCaptureSettings; 135 | end; 136 | 137 | procedure TFormMain.FormDestroy(Sender: TObject); 138 | begin 139 | FBitmap.Free; 140 | end; 141 | 142 | procedure TFormMain.PaintBoxPaint(Sender: TObject; Canvas: TCanvas); 143 | var 144 | SR, DR, PR: TRectF; 145 | begin 146 | if (CheckBoxDisplay.IsChecked) then 147 | begin 148 | PR := RectF(0, 0, PaintBox.Width, PaintBox.Height); 149 | Canvas.Fill.Kind := TBrushKind.Solid; 150 | Canvas.Fill.Color := TAlphaColors.Black; 151 | Canvas.FillRect(PR, 0, 0, [], 1); 152 | 153 | if (FBitmap.Width > 0) then 154 | begin 155 | SR := RectF(0, 0, FBitmap.Width, FBitmap.Height); 156 | DR := SR; 157 | if (DR.Width < PaintBox.Width) and (DR.Height < PaintBox.Height) then 158 | RectCenter(DR, PR) 159 | else 160 | DR := DR.FitInto(PR); 161 | Canvas.DrawBitmap(FBitmap, SR, DR, 1); 162 | end; 163 | end; 164 | end; 165 | 166 | procedure TFormMain.PopupBoxSettingChange(Sender: TObject); 167 | var 168 | Setting: TVideoCaptureSetting; 169 | begin 170 | if (FUpdating) then 171 | Exit; 172 | 173 | if (PopupBoxSetting.ItemIndex < 0) or (PopupBoxSetting.ItemIndex >= Length(FCaptureSettings)) then 174 | Exit; 175 | 176 | Setting := FCaptureSettings[PopupBoxSetting.ItemIndex]; 177 | 178 | CameraComponent.Active := False; 179 | CameraComponent.CaptureSetting := Setting; 180 | CameraComponent.Active := True; 181 | 182 | ResetCapture; 183 | end; 184 | 185 | procedure TFormMain.ResetCapture; 186 | begin 187 | LabelFPS.Text := 'Starting capture...'; 188 | FFrameCount := 0; 189 | FStopwatch := TStopwatch.StartNew; 190 | end; 191 | 192 | procedure TFormMain.UpdateCaptureSettings; 193 | var 194 | Setting, MaxSetting: TVideoCaptureSetting; 195 | UsefulSettings: TDictionary; 196 | Size: TSize; 197 | I: Integer; 198 | begin 199 | { GetAvailableCaptureSettings can return A LOT of settings. For each supported 200 | resolution, it can return a large number of settings with different frame 201 | rates. We only care about the highest framerate supported by each 202 | resolution. We use a dictionary to keep track of this. } 203 | UsefulSettings := TDictionary.Create; 204 | try 205 | for Setting in CameraComponent.GetDefaultCanvasCaptureSettings do 206 | begin 207 | Size := TSize.Create(Setting.Width, Setting.Height); 208 | if (UsefulSettings.TryGetValue(Size, MaxSetting)) then 209 | begin 210 | { Dictionary contains requested resolution. Update its framerate to the 211 | maximum supported one. } 212 | if (Setting.FrameRate > MaxSetting.FrameRate) then 213 | UsefulSettings.AddOrSetValue(Size, Setting); 214 | end 215 | else 216 | UsefulSettings.Add(Size, Setting); 217 | end; 218 | 219 | { Now we can get a list of settings, with only one per resolution. We sort it 220 | maually by resolution. } 221 | FCaptureSettings := UsefulSettings.Values.ToArray; 222 | TArray.Sort(FCaptureSettings, 223 | TComparer.Construct( 224 | function (const Left, Right: TVideoCaptureSetting): Integer 225 | var 226 | Difference: Integer; 227 | begin 228 | Difference := (Left.Width * Left.Height) - (Right.Width * Right.Height); 229 | if (Difference < 0) then 230 | Result := 1 231 | else if (Difference > 0) then 232 | Result := -1 233 | else 234 | Result := 0; 235 | end)); 236 | finally 237 | UsefulSettings.Free; 238 | end; 239 | 240 | { Populate popup box with settings } 241 | FUpdating := True; 242 | try 243 | PopupBoxSetting.BeginUpdate; 244 | try 245 | PopupBoxSetting.Items.Clear; 246 | for I := 0 to Length(FCaptureSettings) - 1 do 247 | begin 248 | Setting := FCaptureSettings[I]; 249 | PopupBoxSetting.Items.Add(Format('%d x %d', [Setting.Width, Setting.Height])); 250 | end; 251 | finally 252 | PopupBoxSetting.EndUpdate; 253 | end; 254 | PopupBoxSetting.ItemIndex := -1; 255 | finally 256 | FUpdating := False; 257 | end; 258 | end; 259 | 260 | end. 261 | -------------------------------------------------------------------------------- /CameraPerformance/Fast/FastUtils.pas: -------------------------------------------------------------------------------- 1 | unit FastUtils; 2 | { Optimized Delphi routines for RGBA<>BGRA conversion, YV12>RGBA conversion and 3 | bitmap rotation } 4 | 5 | interface 6 | 7 | { Swaps the Red and Blue components of pixels in a memory buffer. 8 | 9 | Parameters: 10 | ASrc: points to the source buffer containing the pixels to convert. 11 | ADst: points to the destination buffer for the converted pixels. May be 12 | the same as ASrc. 13 | APixelCount: the number of pixels to convert. 14 | 15 | The Src and Dst buffers must have room for at least PixelCount * 4 bytes. } 16 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 17 | 18 | { Converts a buffer from YV12 format to RGBA format. 19 | 20 | Parameters: 21 | AYPtr: pointer to the source Y (luminance) plane 22 | AUPtr: pointer to the source U (chrominance) plane 23 | AVPtr: pointer to the source V (chrominance) plane 24 | ARGBAPtr: pointer to the target interleaved RGBA buffer 25 | AYStride: number of bytes between two rows in the Y plane 26 | AUVStride: number of bytes between two rows in the U and V planes 27 | ARGBAStride: number of bytes between two rows in the RGBA buffer 28 | AWidth: width of the image to convert (must be even). 29 | AHeight: height of the image to convert (must be even). 30 | 31 | The buffers must be large enough to accomodate AWidth * AHeight pixels in 32 | their corresponding format. 33 | 34 | The alpha values will be set to $FF (opaque) 35 | 36 | NOTE: Currently, this procedure only works when AWidth is a multiple of 16 and 37 | AHeight is a multiple of 2. If this is not the case, then some rightmost and 38 | bottommost pixels will not get converted. } 39 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 40 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 41 | 42 | { Rotates a 32-bit bitmap 0, 90, 180 or 270 degrees. 43 | 44 | Parameters: 45 | ASrc: pointer to the source bitmap data 46 | ADst: pointer to the target bitmap data. This must be different than ASrc. 47 | The ASrc and ADst buffers may not share any data. 48 | ASrcWidth: width of the source bitmap (must be a multiple of 4) 49 | ASrcHeight: height of the source bitmap (must be a multiple of 4) 50 | AAngle: the angle of rotation (0, 90, 180 or 270) 51 | 52 | When rotating 0 or 180 degrees, the dimensions of ADst must match the 53 | dimensions of ASrc. When rotating 90 or 270 degrees, the width of ASrc must 54 | match the height of ADst and the height of ASrc must match the width of ADst. 55 | 56 | Furthermore, this routine expects the dimensions to be a multiple of 4. If 57 | not, an assertion will be raised and the results may be unpredictable. } 58 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 59 | ASrcHeight: Integer; const AAngle: Integer); 60 | 61 | implementation 62 | 63 | uses 64 | System.UITypes; 65 | 66 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 67 | var 68 | I: Integer; 69 | S, D: PAlphaColorRec; 70 | Temp: Byte; 71 | begin 72 | if (ASrc = ADst) then 73 | begin 74 | D := ADst; 75 | for I := 0 to APixelCount - 1 do 76 | begin 77 | Temp := D.B; 78 | D.B := D.R; 79 | D.R := Temp; 80 | Inc(D); 81 | end; 82 | end 83 | else 84 | begin 85 | S := ASrc; 86 | D := ADst; 87 | for I := 0 to APixelCount - 1 do 88 | begin 89 | D.B := S.R; 90 | D.G := S.G; 91 | D.R := S.B; 92 | D.A := S.A; 93 | Inc(S); 94 | Inc(D); 95 | end; 96 | end; 97 | end; 98 | 99 | const 100 | SHIFT = 6; 101 | MAX_VAL = (256 shl SHIFT) - 1; 102 | 103 | function Clip(const AValue: Integer): Integer; inline; 104 | begin 105 | if (AValue < 0) then 106 | Result := 0 107 | else if (AValue > MAX_VAL) then 108 | Result := MAX_VAL 109 | else 110 | Result := AValue; 111 | end; 112 | 113 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 114 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 115 | { This version uses relative low-precision 2.6 integer arithmetic to match the 116 | NEON version. 117 | 118 | Formulas: 119 | R := 1.164*(Y-16) + 1.596*(V-128) 120 | G := 1.164*(Y-16) - 0.391*(U-128) - 0.813*(V-128) 121 | B := 1.164*(Y-16) + 2.018*(U-128) 122 | 123 | We use 2.6 integer arithmetic, so the formulas become: 124 | R := (74*(Y-16) + 102*(V-128)) shr 6 125 | G := (74*(Y-16) - 25*(U-128) - 52*(V-128)) shr 6 126 | B := (74*(Y-16) + 129*(U-128) ) shr 6 127 | 128 | NOTE: we use "127*(U-128)" instead of "129*(U-128)" to match the ARM SIMD 129 | version. } 130 | const 131 | Y_BIAS = 16; 132 | UV_BIAS = 128; 133 | 134 | U_TO_G = 25; 135 | U_TO_B = 127; // Should be 129 136 | V_TO_R = 102; 137 | V_TO_G = 52; 138 | Y_TO_RGB = 74; 139 | 140 | R_INDEX = 0; 141 | G_INDEX = 1; 142 | B_INDEX = 2; 143 | A_INDEX = 3; 144 | var 145 | PaddedWidth, RGBAExtra, YExtra, UVExtra, Row, Col, Y, U, V: Integer; 146 | VtoR, UtoB, UVtoG: Integer; 147 | YPtr, UPtr, VPtr, RGBA: PByte; 148 | begin 149 | if (AWidth <= 0) or (AHeight <= 0) then 150 | Exit; 151 | 152 | Assert(Assigned(AYPtr)); 153 | Assert(Assigned(AUPtr)); 154 | Assert(Assigned(AVPtr)); 155 | Assert(Assigned(ARGBAPtr)); 156 | Assert(AYStride > 0); 157 | Assert(AUVStride > 0); 158 | Assert(ARGBAStride > 0); 159 | Assert((AWidth and 1) = 0); 160 | Assert((AHeight and 1) = 0); 161 | 162 | PaddedWidth := (AWidth + 1) and (not 1); 163 | RGBAExtra := (ARGBAStride - (4 * PaddedWidth)) + ARGBAStride; 164 | YExtra := (AYStride - PaddedWidth) + AYStride; 165 | UVExtra := AUVStride - (PaddedWidth shr 1); 166 | 167 | YPtr := AYPtr; 168 | UPtr := AUPtr; 169 | VPtr := AVPtr; 170 | RGBA := ARGBAPtr; 171 | 172 | Row := 0; 173 | while (Row < AHeight) do 174 | begin 175 | Col := 0; 176 | while (Col < AWidth) do 177 | begin 178 | U := UPtr[0] - UV_BIAS; 179 | V := VPtr[0] - UV_BIAS; 180 | 181 | VtoR := V_TO_R * V; 182 | UVtoG := (U_TO_G * U) + (V_TO_G * V); 183 | UtoB := U_TO_B * U; 184 | 185 | Y := (YPtr[0] - Y_BIAS) * Y_TO_RGB; 186 | RGBA[R_INDEX] := Clip(Y + VtoR) shr SHIFT; 187 | RGBA[G_INDEX] := Clip(Y - UVtoG) shr SHIFT; 188 | RGBA[B_INDEX] := Clip(Y + UtoB) shr SHIFT; 189 | RGBA[A_INDEX] := $FF; 190 | 191 | Y := (YPtr[1] - Y_BIAS) * Y_TO_RGB; 192 | RGBA[R_INDEX + 4] := Clip(Y + VtoR) shr SHIFT; 193 | RGBA[G_INDEX + 4] := Clip(Y - UVtoG) shr SHIFT; 194 | RGBA[B_INDEX + 4] := Clip(Y + UtoB) shr SHIFT; 195 | RGBA[A_INDEX + 4] := $FF; 196 | 197 | Y := (YPtr[AYStride] - Y_BIAS) * Y_TO_RGB; 198 | RGBA[ARGBAStride + R_INDEX] := Clip(Y + VtoR) shr SHIFT; 199 | RGBA[ARGBAStride + G_INDEX] := Clip(Y - UVtoG) shr SHIFT; 200 | RGBA[ARGBAStride + B_INDEX] := Clip(Y + UtoB) shr SHIFT; 201 | RGBA[ARGBAStride + A_INDEX] := $FF; 202 | 203 | Y := (YPtr[AYStride + 1] - Y_BIAS) * Y_TO_RGB; 204 | RGBA[ARGBAStride + R_INDEX + 4] := Clip(Y + VtoR) shr SHIFT; 205 | RGBA[ARGBAStride + G_INDEX + 4] := Clip(Y - UVtoG) shr SHIFT; 206 | RGBA[ARGBAStride + B_INDEX + 4] := Clip(Y + UtoB) shr SHIFT; 207 | RGBA[ARGBAStride + A_INDEX + 4] := $FF; 208 | 209 | Inc(RGBA, 8); 210 | Inc(YPtr, 2); 211 | Inc(UPtr); 212 | Inc(VPtr); 213 | Inc(Col, 2); 214 | end; 215 | Inc(RGBA, RGBAExtra); 216 | Inc(YPtr, YExtra); 217 | Inc(UPtr, UVExtra); 218 | Inc(VPtr, UVExtra); 219 | Inc(Row, 2); 220 | end; 221 | end; 222 | 223 | procedure RotateBitmap0Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 224 | ASrcHeight: Integer); 225 | begin 226 | Move(ASrc^, ADst^, ASrcWidth * ASrcHeight * 4); 227 | end; 228 | 229 | procedure RotateBitmap90Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 230 | ASrcHeight: Integer); 231 | var 232 | S, D: PCardinal; 233 | DstX, DstY, DstDelta: Integer; 234 | begin 235 | S := ASrc; 236 | D := ADst; 237 | Inc(D, ASrcHeight - 1); 238 | 239 | DstDelta := (ASrcWidth * ASrcHeight) + 1; 240 | for DstX := 0 to ASrcHeight - 1 do 241 | begin 242 | for DstY := 0 to ASrcWidth - 1 do 243 | begin 244 | D^ := S^; 245 | Inc(S); 246 | Inc(D, ASrcHeight); 247 | end; 248 | Dec(D, DstDelta); 249 | end; 250 | end; 251 | 252 | procedure RotateBitmap180Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 253 | ASrcHeight: Integer); 254 | var 255 | S, D: PCardinal; 256 | I: Integer; 257 | begin 258 | S := ASrc; 259 | D := ADst; 260 | Inc(D, (ASrcWidth * ASrcHeight) - 1); 261 | for I := 0 to (ASrcWidth * ASrcHeight) - 1 do 262 | begin 263 | D^ := S^; 264 | Inc(S); 265 | Dec(D); 266 | end; 267 | end; 268 | 269 | procedure RotateBitmap270Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 270 | ASrcHeight: Integer); 271 | var 272 | S, D: PCardinal; 273 | DstX, DstY, SrcDelta: Integer; 274 | begin 275 | S := ASrc; 276 | D := ADst; 277 | Inc(S, ASrcWidth - 1); 278 | 279 | SrcDelta := (ASrcHeight * ASrcWidth) + 1; 280 | for DstY := 0 to ASrcWidth - 1 do 281 | begin 282 | for DstX := 0 to ASrcHeight - 1 do 283 | begin 284 | D^ := S^; 285 | Inc(S, ASrcWidth); 286 | Inc(D); 287 | end; 288 | Dec(S, SrcDelta); 289 | end; 290 | end; 291 | 292 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 293 | ASrcHeight: Integer; const AAngle: Integer); 294 | begin 295 | if (ASrcWidth <= 0) or (ASrcHeight <= 0) then 296 | Exit; 297 | 298 | Assert(Assigned(ASrc)); 299 | Assert(Assigned(ADst)); 300 | Assert((ASrcHeight and 3) = 0); 301 | Assert((ASrcWidth and 3) = 0); 302 | 303 | case AAngle of 304 | 0: RotateBitmap0Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 305 | 90: RotateBitmap90Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 306 | 180: RotateBitmap180Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 307 | 270: RotateBitmap270Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 308 | else 309 | Assert(False); 310 | end; 311 | end; 312 | 313 | end. 314 | -------------------------------------------------------------------------------- /CameraPerformance/SIMD/FastUtils.pas: -------------------------------------------------------------------------------- 1 | unit FastUtils; 2 | { NEON/Arm64 optimized assembly routines for RGBA<>BGRA conversion, YV12>RGBA 3 | conversion and bitmap rotation } 4 | 5 | interface 6 | 7 | {$IFDEF IOS} 8 | { Swaps the Red and Blue components of pixels in a memory buffer. 9 | 10 | Parameters: 11 | ASrc: points to the source buffer containing the pixels to convert. 12 | ADst: points to the destination buffer for the converted pixels. May be 13 | the same as ASrc. 14 | APixelCount: the number of pixels to convert. 15 | 16 | The Src and Dst buffers must have room for at least PixelCount * 4 bytes. } 17 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 18 | {$ENDIF} 19 | 20 | {$IFDEF ANDROID} 21 | { Converts a buffer from YV12 format to RGBA format. 22 | 23 | Parameters: 24 | AYPtr: pointer to the source Y (luminance) plane 25 | AUPtr: pointer to the source U (chrominance) plane 26 | AVPtr: pointer to the source V (chrominance) plane 27 | ARGBAPtr: pointer to the target interleaved RGBA buffer 28 | AYStride: number of bytes between two rows in the Y plane 29 | AUVStride: number of bytes between two rows in the U and V planes 30 | ARGBAStride: number of bytes between two rows in the RGBA buffer 31 | AWidth: width of the image to convert (must be even). 32 | AHeight: height of the image to convert (must be even). 33 | 34 | The buffers must be large enough to accomodate AWidth * AHeight pixels in 35 | their corresponding format. 36 | 37 | The alpha values will be set to $FF (opaque) 38 | 39 | NOTE: Currently, this procedure only works when AWidth is a multiple of 16 and 40 | AHeight is a multiple of 2. If this is not the case, then some rightmost and 41 | bottommost pixels will not get converted. } 42 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 43 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 44 | 45 | { Rotates a 32-bit bitmap 0, 90, 180 or 270 degrees. 46 | 47 | Parameters: 48 | ASrc: pointer to the source bitmap data 49 | ADst: pointer to the target bitmap data. This must be different than ASrc. 50 | The ASrc and ADst buffers may not share any data. 51 | ASrcWidth: width of the source bitmap (must be a multiple of 4) 52 | ASrcHeight: height of the source bitmap (must be a multiple of 4) 53 | AAngle: the angle of rotation (0, 90, 180 or 270) 54 | 55 | When rotating 0 or 180 degrees, the dimensions of ADst must match the 56 | dimensions of ASrc. When rotating 90 or 270 degrees, the width of ASrc must 57 | match the height of ADst and the height of ASrc must match the width of ADst. 58 | 59 | Furthermore, this routine expects the dimensions to be a multiple of 4. If 60 | not, an assertion will be raised and the results may be unpredictable. } 61 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 62 | ASrcHeight: Integer; const AAngle: Integer); 63 | {$ENDIF} 64 | 65 | implementation 66 | 67 | uses 68 | System.UITypes; 69 | 70 | const 71 | {$IF Defined(IOS)} 72 | LIB_FAST_UTILS = 'libfastutils.a'; 73 | _PU = ''; 74 | {$ELSEIF Defined(ANDROID)} 75 | LIB_FAST_UTILS = 'libfastutils-android.a'; 76 | _PU = '_'; 77 | {$ENDIF} 78 | 79 | {$IFDEF IOS} 80 | procedure swap_rb(ASrc, ADst: Pointer; ACount: Integer); cdecl; 81 | external LIB_FAST_UTILS name _PU + 'swap_rb'; 82 | 83 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 84 | var 85 | NeonCount, Remainder: Integer; 86 | S, D: PAlphaColorRec; 87 | Temp: Byte; 88 | begin 89 | NeonCount := APixelCount shr 4; 90 | Remainder := APixelCount and 15; 91 | 92 | if (NeonCount > 0) then 93 | swap_rb(ASrc, ADst, NeonCount); 94 | 95 | if (Remainder > 0) then 96 | begin 97 | S := ASrc; 98 | D := ADst; 99 | Inc(S, NeonCount * 16); 100 | Inc(D, NeonCount * 16); 101 | if (ASrc = ADst) then 102 | begin 103 | while (Remainder > 0) do 104 | begin 105 | Temp := D.B; 106 | D.B := D.R; 107 | D.R := Temp; 108 | Inc(D); 109 | Dec(Remainder); 110 | end; 111 | end 112 | else 113 | begin 114 | while (Remainder > 0) do 115 | begin 116 | D.B := S.R; 117 | D.G := S.G; 118 | D.R := S.B; 119 | D.A := S.A; 120 | Inc(S); 121 | Inc(D); 122 | Dec(Remainder); 123 | end; 124 | end; 125 | end; 126 | end; 127 | {$ENDIF} 128 | 129 | {$IFDEF ANDROID} 130 | procedure yv12_to_rgba(AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 131 | AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); cdecl; 132 | external LIB_FAST_UTILS name _PU + 'yv12_to_rgba'; 133 | 134 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 135 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 136 | begin 137 | yv12_to_rgba(AYPtr, AUPtr, AVPtr, ARGBAPtr, AYStride, AUVStride, 138 | ARGBAStride, AWidth and (not 15), AHeight and (not 1)); 139 | end; 140 | 141 | procedure RotateBitmap0Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 142 | ASrcHeight: Integer); 143 | begin 144 | Move(ASrc^, ADst^, ASrcWidth * ASrcHeight * 4); 145 | end; 146 | 147 | procedure RotateBitmap90Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 148 | external LIB_FAST_UTILS name _PU + 'rotate_90'; 149 | 150 | procedure RotateBitmap180Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 151 | external LIB_FAST_UTILS name _PU + 'rotate_180'; 152 | 153 | procedure RotateBitmap270Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 154 | external LIB_FAST_UTILS name _PU + 'rotate_270'; 155 | 156 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 157 | ASrcHeight: Integer; const AAngle: Integer); 158 | begin 159 | if (ASrcWidth <= 0) or (ASrcHeight <= 0) then 160 | Exit; 161 | 162 | Assert(Assigned(ASrc)); 163 | Assert(Assigned(ADst)); 164 | Assert((ASrcHeight and 3) = 0); 165 | Assert((ASrcWidth and 3) = 0); 166 | 167 | case AAngle of 168 | 0: RotateBitmap0Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 169 | 90: RotateBitmap90Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 170 | 180: RotateBitmap180Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 171 | 270: RotateBitmap270Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 172 | else 173 | Assert(False); 174 | end; 175 | end; 176 | {$ENDIF} 177 | 178 | end. 179 | -------------------------------------------------------------------------------- /CameraPerformance/SIMD/libfastutils-android.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/CameraPerformance/SIMD/libfastutils-android.a -------------------------------------------------------------------------------- /CameraPerformance/SIMD/libfastutils.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/CameraPerformance/SIMD/libfastutils.a -------------------------------------------------------------------------------- /DonationList.md: -------------------------------------------------------------------------------- 1 | # 捐助名单 Donation list 2 | 3 | 感谢 Leo (1505250187) 对项目的捐助 2017-09-01 -------------------------------------------------------------------------------- /FMXPrint/FMXPrintDemo.dpr: -------------------------------------------------------------------------------- 1 | program FMXPrintDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | PrintDemoMain in 'PrintDemoMain.pas' {Form30}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm30, Form30); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /FMXPrint/PrintDemoMain.fmx: -------------------------------------------------------------------------------- 1 | object Form30: TForm30 2 | Left = 0 3 | Top = 0 4 | Caption = 'PrintMainForm' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object btn1: TButton 12 | Position.X = 200.000000000000000000 13 | Position.Y = 72.000000000000000000 14 | Size.Width = 185.000000000000000000 15 | Size.Height = 49.000000000000000000 16 | Size.PlatformDefault = False 17 | TabOrder = 0 18 | Text = 'Print Demo' 19 | OnClick = btn1Click 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /FMXPrint/PrintDemoMain.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/FMXPrint/PrintDemoMain.pas -------------------------------------------------------------------------------- /Gif2PngDemo/Gif2PngDemo.dpr: -------------------------------------------------------------------------------- 1 | program Gif2PngDemo; 2 | 3 | uses 4 | Vcl.Forms, 5 | GifDemoMain in 'GifDemoMain.pas' {Form31}; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.CreateForm(TForm31, Form31); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Gif2PngDemo/Gif2PngDemo.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/Gif2PngDemo/Gif2PngDemo.res -------------------------------------------------------------------------------- /Gif2PngDemo/Gif2PngDemo.stat: -------------------------------------------------------------------------------- 1 | [Stats] 2 | EditorSecs=1 3 | DesignerSecs=16 4 | InspectorSecs=1 5 | CompileSecs=1255 6 | OtherSecs=17 7 | StartTime=2016/6/3 8:37:23 8 | RealKeys=0 9 | EffectiveKeys=0 10 | DebugSecs=1 11 | -------------------------------------------------------------------------------- /Gif2PngDemo/GifDemoMain.dfm: -------------------------------------------------------------------------------- 1 | object Form31: TForm31 2 | Left = 0 3 | Top = 0 4 | Caption = 'Gif2Png Demo' 5 | ClientHeight = 161 6 | ClientWidth = 600 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | PixelsPerInch = 96 15 | TextHeight = 13 16 | object Label1: TLabel 17 | Left = 24 18 | Top = 67 19 | Width = 28 20 | Height = 13 21 | Caption = 'Width' 22 | end 23 | object Label2: TLabel 24 | Left = 248 25 | Top = 67 26 | Width = 31 27 | Height = 13 28 | Caption = 'Height' 29 | end 30 | object Button1: TButton 31 | Left = 512 32 | Top = 24 33 | Width = 75 34 | Height = 25 35 | Caption = 'Convert' 36 | TabOrder = 0 37 | OnClick = Button1Click 38 | end 39 | object edtFilename: TEdit 40 | Left = 24 41 | Top = 26 42 | Width = 465 43 | Height = 21 44 | TabOrder = 1 45 | Text = '..\..\Test.gif' 46 | end 47 | object edtWidth: TEdit 48 | Left = 72 49 | Top = 64 50 | Width = 121 51 | Height = 21 52 | ReadOnly = True 53 | TabOrder = 2 54 | end 55 | object edtHeight: TEdit 56 | Left = 312 57 | Top = 64 58 | Width = 121 59 | Height = 21 60 | ReadOnly = True 61 | TabOrder = 3 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /Gif2PngDemo/GifDemoMain.pas: -------------------------------------------------------------------------------- 1 | unit GifDemoMain; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, 8 | Winapi.GDIPAPI, Winapi.GDIPOBJ, Winapi.GDIPUTIL, Vcl.ExtCtrls, 9 | System.IOUtils, System.TypInfo; 10 | 11 | type 12 | TForm31 = class(TForm) 13 | Button1: TButton; 14 | edtFilename: TEdit; 15 | Label1: TLabel; 16 | Label2: TLabel; 17 | edtWidth: TEdit; 18 | edtHeight: TEdit; 19 | procedure Button1Click(Sender: TObject); 20 | private 21 | { Private declarations } 22 | public 23 | { Public declarations } 24 | end; 25 | 26 | var 27 | Form31: TForm31; 28 | 29 | implementation 30 | 31 | {$R *.dfm} 32 | 33 | procedure TForm31.Button1Click(Sender: TObject); 34 | var 35 | Image: TGPImage; 36 | ImageControl: TImage; 37 | I, PageCount, RowCount: Integer; 38 | PngImage: TGPBitmap; 39 | G: TGPGraphics; 40 | pngFileName: string; 41 | s: Status; 42 | ClsID: TGUID; 43 | w, h: Integer; 44 | begin 45 | Image := TGPImage.Create(edtFilename.Text); 46 | try 47 | edtWidth.Text := IntToStr(Image.GetWidth); 48 | edtHeight.Text := IntToStr(Image.GetHeight); 49 | PageCount := Image.GetFrameCount(FrameDimensionTime); 50 | 51 | RowCount := (PageCount + 4) div 5; 52 | w := Image.GetWidth * 5; 53 | h := Image.GetHeight * RowCount; 54 | PngImage := TGPBitmap.Create(w, h); 55 | G := TGPGraphics.Create(PngImage); 56 | try 57 | for I := 0 to PageCount-1 do 58 | begin 59 | Image.SelectActiveFrame(FrameDimensionTime, I); 60 | G.DrawImage(Image, 61 | (I mod 5) * Image.GetWidth, (I div 5) * Image.GetHeight, 62 | Image.GetWidth, Image.GetHeight); 63 | end; 64 | pngFileName := TPath.ChangeExtension(edtFilename.Text, '.png'); 65 | if GetEncoderClsid('image/png',Clsid) >= 0 then 66 | begin 67 | s := PngImage.Save(pngFileName, ClsID); 68 | // label3.Caption := 'Error' + GetEnumName(TypeInfo(Status), 69 | // integer(s)) ; 70 | end; 71 | finally 72 | G.Free; 73 | PngImage.Free; 74 | end; 75 | finally 76 | Image.Free; 77 | end; 78 | end; 79 | 80 | end. 81 | -------------------------------------------------------------------------------- /Gif2PngDemo/Test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/Gif2PngDemo/Test.gif -------------------------------------------------------------------------------- /Gif2PngDemo/Test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/Gif2PngDemo/Test.png -------------------------------------------------------------------------------- /HtmlParserTest/HtmlParserTest.dpr: -------------------------------------------------------------------------------- 1 | program HtmlParserTest; 2 | 3 | uses 4 | Vcl.Forms, 5 | HtmlParserTestMain in 'HtmlParserTestMain.pas' {Form16}, 6 | DOMCore in 'htmlp\DOMCore.pas', 7 | Entities in 'htmlp\Entities.pas', 8 | Formatter in 'htmlp\Formatter.pas', 9 | HTMLParser in 'htmlp\HTMLParser.pas', 10 | HtmlReader in 'htmlp\HtmlReader.pas', 11 | HtmlTags in 'htmlp\HtmlTags.pas', 12 | WStrings in 'htmlp\WStrings.pas'; 13 | 14 | {$R *.res} 15 | 16 | begin 17 | Application.Initialize; 18 | Application.MainFormOnTaskbar := True; 19 | Application.CreateForm(TForm16, Form16); 20 | Application.Run; 21 | end. 22 | -------------------------------------------------------------------------------- /HtmlParserTest/HtmlParserTest.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {EC1AC04C-625B-48CB-B12D-AB291F79A569} 4 | 15.4 5 | VCL 6 | HtmlParserTest.dpr 7 | True 8 | Debug 9 | Win32 10 | 1 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Cfg_1 29 | true 30 | true 31 | 32 | 33 | true 34 | Base 35 | true 36 | 37 | 38 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 39 | $(BDS)\bin\default_app.manifest 40 | 2052 41 | $(BDS)\bin\delphi_PROJECTICON.ico 42 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 43 | HtmlParserTest 44 | .\$(Platform)\$(Config) 45 | .\$(Platform)\$(Config) 46 | false 47 | false 48 | false 49 | false 50 | false 51 | 52 | 53 | .\ 54 | true 55 | JvBDE;JvGlobus;UnitSystem;JvMM;TeeGL920;JvManagedThreads;SmartComponents;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;ZRGraph;ZRLicense;FireDACPgDriver;TeeLanguage920;fmx;RaizeComponentsVcl;IndySystem;JvDlgs;JvCrypt;tethering;TP_LockBox3;NativeXmlPkg;ZRCore;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;TeeDB920;JvNet;DataSnapProviderClient;TeeUI920;DBXSybaseASEDriver;JvDotNetCtrls;DbxCommonDriver;vclimg;FmxTeeUI920;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;FMXTee920;SynEdit_RXE6;JvXPCtrls;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;ColorMapComponents;DBXOracleDriver;CustomIPTransport;JvCore;vclribbon;dsnap;IndyIPServer;FMXTeeLanguage920;fmxase;vcl;IndyCore;tmsxlsdXE6;mbColorLib;DBXMSSQLDriver;CloudService;IndyIPCommon;TsiLang_XE6r;FireDACIBDriver;TeeImage920;DataSnapFireDAC;FireDACDBXDriver;JvAppFrm;soapserver;JvDB;JvRuntimeDesign;inetdbxpress;GLScene_RunTime_VCL;dsnapxml;tmsdXE6;FireDACInfxDriver;FireDACDb2Driver;JclDeveloperTools;ALGLIB;JvDocking;adortl;FMXTeePro920;TeePro920;JvWizards;madBasic_;FireDACASADriver;JvHMI;TeeMaker120;TeeTree2D20Tee9;bindcompfmx;JvBands;vcldbx;RaizeComponentsVclDb;FireDACODBCDriver;RESTBackendComponents;rtl;dbrtl;DbxClientDriver;SmartStorage;FireDACCommon;bindcomp;inetdb;JvPluginSystem;JclContainers;DBXOdbcDriver;JvCmp;vclFireDAC;madDisAsm_;AlgorithmProvider;JvSystem;xmlrtl;DataSnapNativeClient;ibxpress;svnui;JvControls;Tee920;JvTimeFramework;IndyProtocols;DBXMySQLDriver;FMXTeeDB920;FireDACCommonDriver;MIT3DPkg;tmswizdXE6;bindcompdbx;bindengine;vclactnband;soaprtl;JvJans;JvPageComps;bindcompvcl;JvStdCtrls;JvCustom;Jcl;vclie;JvPrintPreview;ZRComponnets;ZRZonationModel;madExcept_;FireDACADSDriver;vcltouch;ZRRockyModel;GraphPackage;PngComponents;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;TeeWorld920;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;JclVcl;JvPascalInterpreter;FireDACMySQLDriver;soapmidas;vclx;tmsexdXE6;ZRLithPack;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;bdertl;GdiPlus;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 56 | 1033 57 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 58 | 59 | 60 | DEBUG;$(DCC_Define) 61 | true 62 | false 63 | true 64 | true 65 | true 66 | 67 | 68 | 1033 69 | true 70 | false 71 | 72 | 73 | false 74 | RELEASE;$(DCC_Define) 75 | 0 76 | 0 77 | 78 | 79 | 80 | MainSource 81 | 82 | 83 |
Form16
84 | dfm 85 |
86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | Cfg_2 96 | Base 97 | 98 | 99 | Base 100 | 101 | 102 | Cfg_1 103 | Base 104 | 105 |
106 | 107 | Delphi.Personality.12 108 | 109 | 110 | 111 | 112 | HtmlParserTest.dpr 113 | 114 | 115 | Microsoft Office 2000 Sample Automation Server Wrapper Components 116 | Microsoft Office XP Sample Automation Server Wrapper Components 117 | 118 | 119 | 120 | 121 | True 122 | 123 | 124 | 12 125 | 126 | 127 | 128 |
129 | -------------------------------------------------------------------------------- /HtmlParserTest/HtmlParserTestMain.dfm: -------------------------------------------------------------------------------- 1 | object Form16: TForm16 2 | Left = 0 3 | Top = 0 4 | Caption = 'Html Parser Test' 5 | ClientHeight = 298 6 | ClientWidth = 849 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | DesignSize = ( 15 | 849 16 | 298) 17 | PixelsPerInch = 96 18 | TextHeight = 13 19 | object btn1: TButton 20 | Left = 749 21 | Top = 8 22 | Width = 75 23 | Height = 25 24 | Anchors = [akTop, akRight] 25 | Caption = 'Parse' 26 | TabOrder = 0 27 | OnClick = btn1Click 28 | ExplicitLeft = 387 29 | end 30 | object lv1: TListView 31 | Left = 8 32 | Top = 8 33 | Width = 735 34 | Height = 281 35 | Anchors = [akLeft, akTop, akRight, akBottom] 36 | Columns = < 37 | item 38 | Caption = 'href' 39 | Width = 240 40 | end 41 | item 42 | Caption = 'Content' 43 | Width = 240 44 | end 45 | item 46 | Caption = 'Date' 47 | Width = 120 48 | end> 49 | ReadOnly = True 50 | TabOrder = 1 51 | ViewStyle = vsReport 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /HtmlParserTest/HtmlParserTestMain.pas: -------------------------------------------------------------------------------- 1 | unit HtmlParserTestMain; 2 | 3 | interface 4 | 5 | uses 6 | Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 7 | Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, 8 | HTMLParser, Vcl.Grids, Vcl.ComCtrls; 9 | 10 | type 11 | TForm16 = class(TForm) 12 | btn1: TButton; 13 | lv1: TListView; 14 | procedure btn1Click(Sender: TObject); 15 | private 16 | { Private declarations } 17 | HtmlParser: THtmlParser; 18 | function LoadHtmlFile: String; 19 | public 20 | { Public declarations } 21 | end; 22 | 23 | var 24 | Form16: TForm16; 25 | 26 | implementation 27 | 28 | uses 29 | DomCore, Formatter; 30 | 31 | {$R *.dfm} 32 | 33 | procedure TForm16.btn1Click(Sender: TObject); 34 | var 35 | HtmlDoc: TDocument; 36 | Formatter: TBaseFormatter; 37 | list: TNodeList; 38 | I: Integer; 39 | span: TNode; 40 | classAttr: TNode; 41 | href: TNode; 42 | Item: TListItem; 43 | begin 44 | HtmlParser := THtmlParser.Create; 45 | try 46 | HtmlDoc := HtmlParser.parseString(LoadHtmlFile); 47 | list := HtmlDoc.getElementsByTagName('span'); 48 | for I := 0 to list.length-1 do 49 | begin 50 | span := list.item(i); 51 | classAttr := span.attributes.getNamedItem('class'); 52 | if Assigned(classAttr) then 53 | begin 54 | if classAttr.childNodes.item(0).NodeValue = 'ina_zh' then 55 | begin 56 | href := span.childNodes.item(0); 57 | if href.nodeName = 'a' then 58 | begin 59 | Item := lv1.Items.Add; 60 | Item.Caption := href.attributes.getNamedItem('href').childNodes.item(0).nodeValue; 61 | Item.SubItems.Add(href.childNodes.item(0).NodeValue); 62 | Item.SubItems.Add(span.parentNode.childNodes.item(2).childNodes.item(0).NodeValue); 63 | end; 64 | end; 65 | end; 66 | end; 67 | list.Free; 68 | finally 69 | HtmlParser.Free 70 | end; 71 | 72 | 73 | 74 | HtmlDoc.Free; 75 | 76 | end; 77 | 78 | function TForm16.LoadHtmlFile: String; 79 | var 80 | F: TFileStream; 81 | Reader: TStreamReader; 82 | begin 83 | F := TFileStream.Create('Test.html', fmOpenRead); 84 | try 85 | Reader := TStreamReader.Create(F); 86 | try 87 | Result := Reader.ReadToEnd; 88 | finally 89 | Reader.Free; 90 | end; 91 | finally 92 | F.Free 93 | end; 94 | end; 95 | 96 | end. 97 | -------------------------------------------------------------------------------- /HtmlParserTest/README.md: -------------------------------------------------------------------------------- 1 | # Html Parser Test for delphi XE6 2 | 3 | This Demo use "Delphi Dom HTML Parser and Converter", the original address is: 4 | 5 | http://sourceforge.net/projects/htmlp/ 6 | 7 | This Demo demonstrate how to use HTML Parser parse a HTML file and get information. 8 | 9 | 这个Demo使用了Delphi Dom HTML Parser and Converter,原始的源代码可以到以下地址下载: 10 | 11 | http://sourceforge.net/projects/htmlp/ 12 | 13 | 该Demo演示了使用HTML Parser解析一个HTML文件,并提取其中信息。 -------------------------------------------------------------------------------- /HtmlParserTest/htmlp/Entities.pas: -------------------------------------------------------------------------------- 1 | unit Entities; 2 | 3 | interface 4 | 5 | const 6 | MaxEntNameLen = 8; 7 | 8 | function GetEntValue(const Name: String): WideChar; 9 | function GetEntName(Code: Word): String; 10 | 11 | implementation 12 | 13 | uses 14 | SysUtils, Classes; 15 | 16 | const 17 | EntCount = 252; 18 | 19 | type 20 | PEntity = ^TEntity; 21 | TEntity = record 22 | Name: String; 23 | Code: Word 24 | end; 25 | 26 | TEntities = array[0..EntCount - 1] of TEntity; 27 | 28 | const 29 | EntTab: TEntities = ( 30 | (Name: 'nbsp'; Code: 160), 31 | (Name: 'iexcl'; Code: 161), 32 | (Name: 'cent'; Code: 162), 33 | (Name: 'pound'; Code: 163), 34 | (Name: 'curren'; Code: 164), 35 | (Name: 'yen'; Code: 165), 36 | (Name: 'brvbar'; Code: 166), 37 | (Name: 'sect'; Code: 167), 38 | (Name: 'uml'; Code: 168), 39 | (Name: 'copy'; Code: 169), 40 | (Name: 'ordf'; Code: 170), 41 | (Name: 'laquo'; Code: 171), 42 | (Name: 'not'; Code: 172), 43 | (Name: 'shy'; Code: 173), 44 | (Name: 'reg'; Code: 174), 45 | (Name: 'macr'; Code: 175), 46 | (Name: 'deg'; Code: 176), 47 | (Name: 'plusmn'; Code: 177), 48 | (Name: 'sup2'; Code: 178), 49 | (Name: 'sup3'; Code: 179), 50 | (Name: 'acute'; Code: 180), 51 | (Name: 'micro'; Code: 181), 52 | (Name: 'para'; Code: 182), 53 | (Name: 'middot'; Code: 183), 54 | (Name: 'cedil'; Code: 184), 55 | (Name: 'sup1'; Code: 185), 56 | (Name: 'ordm'; Code: 186), 57 | (Name: 'raquo'; Code: 187), 58 | (Name: 'frac14'; Code: 188), 59 | (Name: 'frac12'; Code: 189), 60 | (Name: 'frac34'; Code: 190), 61 | (Name: 'iquest'; Code: 191), 62 | (Name: 'Agrave'; Code: 192), 63 | (Name: 'Aacute'; Code: 193), 64 | (Name: 'Acirc'; Code: 194), 65 | (Name: 'Atilde'; Code: 195), 66 | (Name: 'Auml'; Code: 196), 67 | (Name: 'Aring'; Code: 197), 68 | (Name: 'AElig'; Code: 198), 69 | (Name: 'Ccedil'; Code: 199), 70 | (Name: 'Egrave'; Code: 200), 71 | (Name: 'Eacute'; Code: 201), 72 | (Name: 'Ecirc'; Code: 202), 73 | (Name: 'Euml'; Code: 203), 74 | (Name: 'Igrave'; Code: 204), 75 | (Name: 'Iacute'; Code: 205), 76 | (Name: 'Icirc'; Code: 206), 77 | (Name: 'Iuml'; Code: 207), 78 | (Name: 'ETH'; Code: 208), 79 | (Name: 'Ntilde'; Code: 209), 80 | (Name: 'Ograve'; Code: 210), 81 | (Name: 'Oacute'; Code: 211), 82 | (Name: 'Ocirc'; Code: 212), 83 | (Name: 'Otilde'; Code: 213), 84 | (Name: 'Ouml'; Code: 214), 85 | (Name: 'times'; Code: 215), 86 | (Name: 'Oslash'; Code: 216), 87 | (Name: 'Ugrave'; Code: 217), 88 | (Name: 'Uacute'; Code: 218), 89 | (Name: 'Ucirc'; Code: 219), 90 | (Name: 'Uuml'; Code: 220), 91 | (Name: 'Yacute'; Code: 221), 92 | (Name: 'THORN'; Code: 222), 93 | (Name: 'szlig'; Code: 223), 94 | (Name: 'agrave'; Code: 224), 95 | (Name: 'aacute'; Code: 225), 96 | (Name: 'acirc'; Code: 226), 97 | (Name: 'atilde'; Code: 227), 98 | (Name: 'auml'; Code: 228), 99 | (Name: 'aring'; Code: 229), 100 | (Name: 'aelig'; Code: 230), 101 | (Name: 'ccedil'; Code: 231), 102 | (Name: 'egrave'; Code: 232), 103 | (Name: 'eacute'; Code: 233), 104 | (Name: 'ecirc'; Code: 234), 105 | (Name: 'euml'; Code: 235), 106 | (Name: 'igrave'; Code: 236), 107 | (Name: 'iacute'; Code: 237), 108 | (Name: 'icirc'; Code: 238), 109 | (Name: 'iuml'; Code: 239), 110 | (Name: 'eth'; Code: 240), 111 | (Name: 'ntilde'; Code: 241), 112 | (Name: 'ograve'; Code: 242), 113 | (Name: 'oacute'; Code: 243), 114 | (Name: 'ocirc'; Code: 244), 115 | (Name: 'otilde'; Code: 245), 116 | (Name: 'ouml'; Code: 246), 117 | (Name: 'divide'; Code: 247), 118 | (Name: 'oslash'; Code: 248), 119 | (Name: 'ugrave'; Code: 249), 120 | (Name: 'uacute'; Code: 250), 121 | (Name: 'ucirc'; Code: 251), 122 | (Name: 'uuml'; Code: 252), 123 | (Name: 'yacute'; Code: 253), 124 | (Name: 'thorn'; Code: 254), 125 | (Name: 'yuml'; Code: 255), 126 | (Name: 'fnof'; Code: 402), 127 | (Name: 'Alpha'; Code: 913), 128 | (Name: 'Beta'; Code: 914), 129 | (Name: 'Gamma'; Code: 915), 130 | (Name: 'Delta'; Code: 916), 131 | (Name: 'Epsilon'; Code: 917), 132 | (Name: 'Zeta'; Code: 918), 133 | (Name: 'Eta'; Code: 919), 134 | (Name: 'Theta'; Code: 920), 135 | (Name: 'Iota'; Code: 921), 136 | (Name: 'Kappa'; Code: 922), 137 | (Name: 'Lambda'; Code: 923), 138 | (Name: 'Mu'; Code: 924), 139 | (Name: 'Nu'; Code: 925), 140 | (Name: 'Xi'; Code: 926), 141 | (Name: 'Omicron'; Code: 927), 142 | (Name: 'Pi'; Code: 928), 143 | (Name: 'Rho'; Code: 929), 144 | (Name: 'Sigma'; Code: 931), 145 | (Name: 'Tau'; Code: 932), 146 | (Name: 'Upsilon'; Code: 933), 147 | (Name: 'Phi'; Code: 934), 148 | (Name: 'Chi'; Code: 935), 149 | (Name: 'Psi'; Code: 936), 150 | (Name: 'Omega'; Code: 937), 151 | (Name: 'alpha'; Code: 945), 152 | (Name: 'beta'; Code: 946), 153 | (Name: 'gamma'; Code: 947), 154 | (Name: 'delta'; Code: 948), 155 | (Name: 'epsilon'; Code: 949), 156 | (Name: 'zeta'; Code: 950), 157 | (Name: 'eta'; Code: 951), 158 | (Name: 'theta'; Code: 952), 159 | (Name: 'iota'; Code: 953), 160 | (Name: 'kappa'; Code: 954), 161 | (Name: 'lambda'; Code: 955), 162 | (Name: 'mu'; Code: 956), 163 | (Name: 'nu'; Code: 957), 164 | (Name: 'xi'; Code: 958), 165 | (Name: 'omicron'; Code: 959), 166 | (Name: 'pi'; Code: 960), 167 | (Name: 'rho'; Code: 961), 168 | (Name: 'sigmaf'; Code: 962), 169 | (Name: 'sigma'; Code: 963), 170 | (Name: 'tau'; Code: 964), 171 | (Name: 'upsilon'; Code: 965), 172 | (Name: 'phi'; Code: 966), 173 | (Name: 'chi'; Code: 967), 174 | (Name: 'psi'; Code: 968), 175 | (Name: 'omega'; Code: 969), 176 | (Name: 'thetasym'; Code: 977), 177 | (Name: 'upsih'; Code: 978), 178 | (Name: 'piv'; Code: 982), 179 | (Name: 'bull'; Code: 8226), 180 | (Name: 'hellip'; Code: 8230), 181 | (Name: 'prime'; Code: 8242), 182 | (Name: 'Prime'; Code: 8243), 183 | (Name: 'oline'; Code: 8254), 184 | (Name: 'frasl'; Code: 8260), 185 | (Name: 'weierp'; Code: 8472), 186 | (Name: 'image'; Code: 8465), 187 | (Name: 'real'; Code: 8476), 188 | (Name: 'trade'; Code: 8482), 189 | (Name: 'alefsym'; Code: 8501), 190 | (Name: 'larr'; Code: 8592), 191 | (Name: 'uarr'; Code: 8593), 192 | (Name: 'rarr'; Code: 8594), 193 | (Name: 'darr'; Code: 8595), 194 | (Name: 'harr'; Code: 8596), 195 | (Name: 'crarr'; Code: 8629), 196 | (Name: 'lArr'; Code: 8656), 197 | (Name: 'uArr'; Code: 8657), 198 | (Name: 'rArr'; Code: 8658), 199 | (Name: 'dArr'; Code: 8659), 200 | (Name: 'hArr'; Code: 8660), 201 | (Name: 'forall'; Code: 8704), 202 | (Name: 'part'; Code: 8706), 203 | (Name: 'exist'; Code: 8707), 204 | (Name: 'empty'; Code: 8709), 205 | (Name: 'nabla'; Code: 8711), 206 | (Name: 'isin'; Code: 8712), 207 | (Name: 'notin'; Code: 8713), 208 | (Name: 'ni'; Code: 8715), 209 | (Name: 'prod'; Code: 8719), 210 | (Name: 'sum'; Code: 8721), 211 | (Name: 'minus'; Code: 8722), 212 | (Name: 'lowast'; Code: 8727), 213 | (Name: 'radic'; Code: 8730), 214 | (Name: 'prop'; Code: 8733), 215 | (Name: 'infin'; Code: 8734), 216 | (Name: 'ang'; Code: 8736), 217 | (Name: 'and'; Code: 8743), 218 | (Name: 'or'; Code: 8744), 219 | (Name: 'cap'; Code: 8745), 220 | (Name: 'cup'; Code: 8746), 221 | (Name: 'int'; Code: 8747), 222 | (Name: 'there4'; Code: 8756), 223 | (Name: 'sim'; Code: 8764), 224 | (Name: 'cong'; Code: 8773), 225 | (Name: 'asymp'; Code: 8776), 226 | (Name: 'ne'; Code: 8800), 227 | (Name: 'equiv'; Code: 8801), 228 | (Name: 'le'; Code: 8804), 229 | (Name: 'ge'; Code: 8805), 230 | (Name: 'sub'; Code: 8834), 231 | (Name: 'sup'; Code: 8835), 232 | (Name: 'nsub'; Code: 8836), 233 | (Name: 'sube'; Code: 8838), 234 | (Name: 'supe'; Code: 8839), 235 | (Name: 'oplus'; Code: 8853), 236 | (Name: 'otimes'; Code: 8855), 237 | (Name: 'perp'; Code: 8869), 238 | (Name: 'sdot'; Code: 8901), 239 | (Name: 'lceil'; Code: 8968), 240 | (Name: 'rceil'; Code: 8969), 241 | (Name: 'lfloor'; Code: 8970), 242 | (Name: 'rfloor'; Code: 8971), 243 | (Name: 'lang'; Code: 9001), 244 | (Name: 'rang'; Code: 9002), 245 | (Name: 'loz'; Code: 9674), 246 | (Name: 'spades'; Code: 9824), 247 | (Name: 'clubs'; Code: 9827), 248 | (Name: 'hearts'; Code: 9829), 249 | (Name: 'diams'; Code: 9830), 250 | (Name: 'quot'; Code: 34), 251 | (Name: 'amp'; Code: 38), 252 | (Name: 'lt'; Code: 60), 253 | (Name: 'gt'; Code: 62), 254 | (Name: 'OElig'; Code: 338), 255 | (Name: 'oelig'; Code: 339), 256 | (Name: 'Scaron'; Code: 352), 257 | (Name: 'scaron'; Code: 353), 258 | (Name: 'Yuml'; Code: 376), 259 | (Name: 'circ'; Code: 710), 260 | (Name: 'tilde'; Code: 732), 261 | (Name: 'ensp'; Code: 8194), 262 | (Name: 'emsp'; Code: 8195), 263 | (Name: 'thinsp'; Code: 8201), 264 | (Name: 'zwnj'; Code: 8204), 265 | (Name: 'zwj'; Code: 8205), 266 | (Name: 'lrm'; Code: 8206), 267 | (Name: 'rlm'; Code: 8207), 268 | (Name: 'ndash'; Code: 8211), 269 | (Name: 'mdash'; Code: 8212), 270 | (Name: 'lsquo'; Code: 8216), 271 | (Name: 'rsquo'; Code: 8217), 272 | (Name: 'sbquo'; Code: 8218), 273 | (Name: 'ldquo'; Code: 8220), 274 | (Name: 'rdquo'; Code: 8221), 275 | (Name: 'bdquo'; Code: 8222), 276 | (Name: 'dagger'; Code: 8224), 277 | (Name: 'Dagger'; Code: 8225), 278 | (Name: 'permil'; Code: 8240), 279 | (Name: 'lsaquo'; Code: 8249), 280 | (Name: 'rsaquo'; Code: 8250), 281 | (Name: 'euro'; Code: 8364) 282 | ); 283 | 284 | type 285 | TEntList = class(TList) 286 | private 287 | function GetCode(const Name: String): Integer; 288 | public 289 | constructor Create; 290 | property Code[const Name: String]: Integer read GetCode; 291 | end; 292 | 293 | var 294 | EntityList: TEntList; 295 | 296 | function EntCompare(Ent1, Ent2: Pointer): Integer; 297 | begin 298 | Result := CompareStr(PEntity(Ent1)^.Name, PEntity(Ent2)^.Name) 299 | end; 300 | 301 | constructor TEntList.Create; 302 | var 303 | I: Integer; 304 | begin 305 | inherited Create; 306 | Capacity := EntCount; 307 | for I := 0 to EntCount - 1 do 308 | Add(@EntTab[I]); 309 | Sort(EntCompare) 310 | end; 311 | 312 | function TEntList.GetCode(const Name: String): Integer; 313 | var 314 | I, L, U, Cmp: Integer; 315 | begin 316 | L := 0; 317 | U := Count - 1; 318 | while L <= U do 319 | begin 320 | I := (L + U) div 2; 321 | Cmp := CompareStr(Name, PEntity(Items[I])^.Name); 322 | if Cmp = 0 then 323 | begin 324 | Result := PEntity(Items[I])^.Code; 325 | Exit 326 | end; 327 | if Cmp < 0 then 328 | U := I - 1 329 | else 330 | L := I + 1 331 | end; 332 | Result := 32 333 | end; 334 | 335 | function GetEntValue(const Name: String): WideChar; 336 | begin 337 | Result := WideChar(EntityList.Code[Name]) 338 | end; 339 | 340 | function GetEntName(Code: Word): String; 341 | var 342 | I: Integer; 343 | begin 344 | for I := 0 to EntCount - 1 do 345 | if EntTab[I].Code = Code then 346 | begin 347 | Result := EntTab[I].Name; 348 | Exit 349 | end; 350 | Result := '' 351 | end; 352 | 353 | initialization 354 | 355 | EntityList := TEntList.Create 356 | 357 | finalization 358 | 359 | EntityList.Free 360 | 361 | end. 362 | -------------------------------------------------------------------------------- /HtmlParserTest/htmlp/HTMLParser.pas: -------------------------------------------------------------------------------- 1 | unit HtmlParser; 2 | 3 | interface 4 | 5 | uses 6 | DomCore, HtmlReader, HtmlTags; 7 | 8 | type 9 | THtmlParser = class 10 | private 11 | FHtmlDocument: TDocument; 12 | FHtmlReader: THtmlReader; 13 | FCurrentNode: TNode; 14 | FCurrentTag: THtmlTag; 15 | function FindDefParent: TElement; 16 | function FindParent: TElement; 17 | function FindParentElement(tagList: THtmlTagSet): TElement; 18 | function FindTableParent: TElement; 19 | function FindThisElement: TElement; 20 | function GetMainElement(const tagName: TDomString): TElement; 21 | procedure ProcessAttributeEnd(Sender: TObject); 22 | procedure ProcessAttributeStart(Sender: TObject); 23 | procedure ProcessCDataSection(Sender: TObject); 24 | procedure ProcessComment(Sender: TObject); 25 | procedure ProcessDocType(Sender: TObject); 26 | procedure ProcessElementEnd(Sender: TObject); 27 | procedure ProcessElementStart(Sender: TObject); 28 | procedure ProcessEndElement(Sender: TObject); 29 | procedure ProcessEntityReference(Sender: TObject); 30 | procedure ProcessTextNode(Sender: TObject); 31 | public 32 | constructor Create; 33 | destructor Destroy; override; 34 | function parseString(const htmlStr: TDomString): TDocument; 35 | property HtmlDocument: TDocument read FHtmlDocument; 36 | end; 37 | 38 | implementation 39 | 40 | const 41 | htmlTagName = 'html'; 42 | headTagName = 'head'; 43 | bodyTagName = 'body'; 44 | 45 | constructor THtmlParser.Create; 46 | begin 47 | inherited Create; 48 | FHtmlReader := THtmlReader.Create; 49 | with FHtmlReader do 50 | begin 51 | OnAttributeEnd := ProcessAttributeEnd; 52 | OnAttributeStart := ProcessAttributeStart; 53 | OnCDataSection := ProcessCDataSection; 54 | OnComment := ProcessComment; 55 | OnDocType := ProcessDocType; 56 | OnElementEnd := ProcessElementEnd; 57 | OnElementStart := ProcessElementStart; 58 | OnEndElement := ProcessEndElement; 59 | OnEntityReference := ProcessEntityReference; 60 | //OnNotation := ProcessNotation; 61 | //OnProcessingInstruction := ProcessProcessingInstruction; 62 | OnTextNode := ProcessTextNode; 63 | end 64 | end; 65 | 66 | destructor THtmlParser.Destroy; 67 | begin 68 | FHtmlReader.Free; 69 | inherited Destroy 70 | end; 71 | 72 | function THtmlParser.FindDefParent: TElement; 73 | begin 74 | if FCurrentTag.Number in [HEAD_TAG, BODY_TAG] then 75 | Result := FHtmlDocument.appendChild(FHtmlDocument.createElement(htmlTagName)) as TElement 76 | else 77 | if FCurrentTag.Number in HeadTags then 78 | Result := GetMainElement(headTagName) 79 | else 80 | Result := GetMainElement(bodyTagName) 81 | end; 82 | 83 | function THtmlParser.FindParent: TElement; 84 | begin 85 | if (FCurrentTag.Number = P_TAG) or (FCurrentTag.Number in BlockTags) then 86 | Result := FindParentElement(BlockParentTags) 87 | else 88 | if FCurrentTag.Number = LI_TAG then 89 | Result := FindParentElement(ListItemParentTags) 90 | else 91 | if FCurrentTag.Number in [DD_TAG, DT_TAG] then 92 | Result := FindParentElement(DefItemParentTags) 93 | else 94 | if FCurrentTag.Number in [TD_TAG, TH_TAG] then 95 | Result := FindParentElement(CellParentTags) 96 | else 97 | if FCurrentTag.Number = TR_TAG then 98 | Result := FindParentElement(RowParentTags) 99 | else 100 | if FCurrentTag.Number = COL_TAG then 101 | Result := FindParentElement(ColParentTags) 102 | else 103 | if FCurrentTag.Number in [COLGROUP_TAG, THEAD_TAG, TFOOT_TAG, TBODY_TAG] then 104 | Result := FindParentElement(TableSectionParentTags) 105 | else 106 | if FCurrentTag.Number = TABLE_TAG then 107 | Result := FindTableParent 108 | else 109 | if FCurrentTag.Number = OPTION_TAG then 110 | Result := FindParentElement(OptionParentTags) 111 | else 112 | if FCurrentTag.Number in [HEAD_TAG, BODY_TAG] then 113 | Result := FHtmlDocument.documentElement as TElement 114 | else 115 | Result := nil; 116 | if Result = nil then 117 | Result := FindDefParent 118 | end; 119 | 120 | function THtmlParser.FindParentElement(tagList: THtmlTagSet): TElement; 121 | var 122 | Node: TNode; 123 | HtmlTag: THtmlTag; 124 | begin 125 | Node := FCurrentNode; 126 | while Node.nodeType = ELEMENT_NODE do 127 | begin 128 | HtmlTag := HtmlTagList.GetTagByName(Node.nodeName); 129 | if HtmlTag.Number in tagList then 130 | begin 131 | Result := Node as TElement; 132 | Exit 133 | end; 134 | Node := Node.parentNode 135 | end; 136 | Result := nil 137 | end; 138 | 139 | function THtmlParser.FindTableParent: TElement; 140 | var 141 | Node: TNode; 142 | HtmlTag: THtmlTag; 143 | begin 144 | Node := FCurrentNode; 145 | while Node.nodeType = ELEMENT_NODE do 146 | begin 147 | HtmlTag := HtmlTagList.GetTagByName(Node.nodeName); 148 | if (HtmlTag.Number = TD_TAG) or (HtmlTag.Number in BlockTags) then 149 | begin 150 | Result := Node as TElement; 151 | Exit 152 | end; 153 | Node := Node.parentNode 154 | end; 155 | Result := GetMainElement(bodyTagName) 156 | end; 157 | 158 | function THtmlParser.FindThisElement: TElement; 159 | var 160 | Node: TNode; 161 | begin 162 | Node := FCurrentNode; 163 | while Node.nodeType = ELEMENT_NODE do 164 | begin 165 | Result := Node as TElement; 166 | if Result.tagName = FHtmlReader.nodeName then 167 | Exit; 168 | Node := Node.parentNode 169 | end; 170 | Result := nil 171 | end; 172 | 173 | function THtmlParser.GetMainElement(const tagName: TDomString): TElement; 174 | var 175 | child: TNode; 176 | I: Integer; 177 | begin 178 | if FHtmlDocument.documentElement = nil then 179 | FHtmlDocument.appendChild(FHtmlDocument.createElement(htmlTagName)); 180 | for I := 0 to FHtmlDocument.documentElement.childNodes.length - 1 do 181 | begin 182 | child := FHtmlDocument.documentElement.childNodes.item(I); 183 | if (child.nodeType = ELEMENT_NODE) and (child.nodeName = tagName) then 184 | begin 185 | Result := child as TElement; 186 | Exit 187 | end 188 | end; 189 | Result := FHtmlDocument.createElement(tagName); 190 | FHtmlDocument.documentElement.appendChild(Result) 191 | end; 192 | 193 | procedure THtmlParser.ProcessAttributeEnd(Sender: TObject); 194 | begin 195 | FCurrentNode := (FCurrentNode as TAttr).ownerElement 196 | end; 197 | 198 | procedure THtmlParser.ProcessAttributeStart(Sender: TObject); 199 | var 200 | Attr: TAttr; 201 | begin 202 | Attr := FHtmlDocument.createAttribute((Sender as THtmlReader).nodeName); 203 | (FCurrentNode as TElement).setAttributeNode(Attr); 204 | FCurrentNode := Attr 205 | end; 206 | 207 | procedure THtmlParser.ProcessCDataSection(Sender: TObject); 208 | var 209 | CDataSection: TCDataSection; 210 | begin 211 | CDataSection := FHtmlDocument.createCDATASection(FHtmlReader.nodeValue); 212 | FCurrentNode.appendChild(CDataSection) 213 | end; 214 | 215 | procedure THtmlParser.ProcessComment(Sender: TObject); 216 | var 217 | Comment: TComment; 218 | begin 219 | Comment := FHtmlDocument.createComment(FHtmlReader.nodeValue); 220 | FCurrentNode.appendChild(Comment) 221 | end; 222 | 223 | procedure THtmlParser.ProcessDocType(Sender: TObject); 224 | begin 225 | with FHtmlReader do 226 | FHtmlDocument.docType := DomImplementation.createDocumentType(nodeName, publicID, systemID); 227 | end; 228 | 229 | procedure THtmlParser.ProcessElementEnd(Sender: TObject); 230 | begin 231 | if FHtmlReader.isEmptyElement or (FCurrentTag.Number in EmptyTags) then 232 | FCurrentNode := FCurrentNode.parentNode; 233 | FCurrentTag := nil 234 | end; 235 | 236 | procedure THtmlParser.ProcessElementStart(Sender: TObject); 237 | var 238 | Element: TElement; 239 | Parent: TNode; 240 | begin 241 | FCurrentTag := HtmlTagList.GetTagByName(FHtmlReader.nodeName); 242 | if FCurrentTag.Number in NeedFindParentTags + BlockTags then 243 | begin 244 | Parent := FindParent; 245 | if not Assigned(Parent) then 246 | raise DomException.Create(HIERARCHY_REQUEST_ERR); 247 | FCurrentNode := Parent 248 | end; 249 | Element := FHtmlDocument.createElement(FHtmlReader.nodeName); 250 | FCurrentNode.appendChild(Element); 251 | FCurrentNode := Element 252 | end; 253 | 254 | procedure THtmlParser.ProcessEndElement(Sender: TObject); 255 | var 256 | Element: TElement; 257 | begin 258 | Element := FindThisElement; 259 | if Assigned(Element) then 260 | FCurrentNode := Element.parentNode 261 | { else 262 | if IsBlockTagName(FHtmlReader.nodeName) then 263 | raise DomException.Create(HIERARCHY_REQUEST_ERR)} 264 | end; 265 | 266 | procedure THtmlParser.ProcessEntityReference(Sender: TObject); 267 | var 268 | EntityReference: TEntityReference; 269 | begin 270 | EntityReference := FHtmlDocument.createEntityReference(FHtmlReader.nodeName); 271 | FCurrentNode.appendChild(EntityReference) 272 | end; 273 | 274 | procedure THtmlParser.ProcessTextNode(Sender: TObject); 275 | var 276 | TextNode: TTextNode; 277 | begin 278 | TextNode := FHtmlDocument.createTextNode(FHtmlReader.nodeValue); 279 | FCurrentNode.appendChild(TextNode) 280 | end; 281 | 282 | function THtmlParser.parseString(const htmlStr: TDomString): TDocument; 283 | begin 284 | FHtmlReader.htmlStr := htmlStr; 285 | FHtmlDocument := DomImplementation.createEmptyDocument(nil); 286 | FCurrentNode := FHtmlDocument; 287 | try 288 | while FHtmlReader.Read do; 289 | except 290 | // TODO: Add event ? 291 | end; 292 | Result := FHtmlDocument 293 | end; 294 | 295 | end. 296 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTest.cfg: -------------------------------------------------------------------------------- 1 | -$A8 2 | -$B- 3 | -$C+ 4 | -$D+ 5 | -$E- 6 | -$F- 7 | -$G+ 8 | -$H+ 9 | -$I+ 10 | -$J- 11 | -$K- 12 | -$L+ 13 | -$M- 14 | -$N+ 15 | -$O+ 16 | -$P+ 17 | -$Q- 18 | -$R- 19 | -$S- 20 | -$T- 21 | -$U- 22 | -$V+ 23 | -$W- 24 | -$X+ 25 | -$YD 26 | -$Z1 27 | -cg 28 | -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; 29 | -H+ 30 | -W+ 31 | -M 32 | -$M16384,1048576 33 | -K$00400000 34 | -LE"c:\program files\borland\delphi7\Projects\Bpl" 35 | -LN"c:\program files\borland\delphi7\Projects\Bpl" 36 | -U";C:\DelphiTools\TeeChart.v8.01.Full.Source.Delphi.BCB.BDS.CRS.ccrun.776754\Sources\Compiled\Delphi7\Lib" 37 | -O";C:\DelphiTools\TeeChart.v8.01.Full.Source.Delphi.BCB.BDS.CRS.ccrun.776754\Sources\Compiled\Delphi7\Lib" 38 | -I";C:\DelphiTools\TeeChart.v8.01.Full.Source.Delphi.BCB.BDS.CRS.ccrun.776754\Sources\Compiled\Delphi7\Lib" 39 | -R";C:\DelphiTools\TeeChart.v8.01.Full.Source.Delphi.BCB.BDS.CRS.ccrun.776754\Sources\Compiled\Delphi7\Lib" 40 | -w-UNSAFE_TYPE 41 | -w-UNSAFE_CODE 42 | -w-UNSAFE_CAST 43 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTest.dof: -------------------------------------------------------------------------------- 1 | [FileVersion] 2 | Version=7.0 3 | [Compiler] 4 | A=8 5 | B=0 6 | C=1 7 | D=1 8 | E=0 9 | F=0 10 | G=1 11 | H=1 12 | I=1 13 | J=0 14 | K=0 15 | L=1 16 | M=0 17 | N=1 18 | O=1 19 | P=1 20 | Q=0 21 | R=0 22 | S=0 23 | T=0 24 | U=0 25 | V=1 26 | W=0 27 | X=1 28 | Y=1 29 | Z=1 30 | ShowHints=1 31 | ShowWarnings=1 32 | UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; 33 | NamespacePrefix= 34 | SymbolDeprecated=1 35 | SymbolLibrary=1 36 | SymbolPlatform=1 37 | UnitLibrary=1 38 | UnitPlatform=1 39 | UnitDeprecated=1 40 | HResultCompat=1 41 | HidingMember=1 42 | HiddenVirtual=1 43 | Garbage=1 44 | BoundsError=1 45 | ZeroNilCompat=1 46 | StringConstTruncated=1 47 | ForLoopVarVarPar=1 48 | TypedConstVarPar=1 49 | AsgToTypedConst=1 50 | CaseLabelRange=1 51 | ForVariable=1 52 | ConstructingAbstract=1 53 | ComparisonFalse=1 54 | ComparisonTrue=1 55 | ComparingSignedUnsigned=1 56 | CombiningSignedUnsigned=1 57 | UnsupportedConstruct=1 58 | FileOpen=1 59 | FileOpenUnitSrc=1 60 | BadGlobalSymbol=1 61 | DuplicateConstructorDestructor=1 62 | InvalidDirective=1 63 | PackageNoLink=1 64 | PackageThreadVar=1 65 | ImplicitImport=1 66 | HPPEMITIgnored=1 67 | NoRetVal=1 68 | UseBeforeDef=1 69 | ForLoopVarUndef=1 70 | UnitNameMismatch=1 71 | NoCFGFileFound=1 72 | MessageDirective=1 73 | ImplicitVariants=1 74 | UnicodeToLocale=1 75 | LocaleToUnicode=1 76 | ImagebaseMultiple=1 77 | SuspiciousTypecast=1 78 | PrivatePropAccessor=1 79 | UnsafeType=0 80 | UnsafeCode=0 81 | UnsafeCast=0 82 | [Linker] 83 | MapFile=0 84 | OutputObjs=0 85 | ConsoleApp=1 86 | DebugInfo=0 87 | RemoteSymbols=0 88 | MinStackSize=16384 89 | MaxStackSize=1048576 90 | ImageBase=4194304 91 | ExeDescription= 92 | [Directories] 93 | OutputDir= 94 | UnitOutputDir= 95 | PackageDLLOutputDir= 96 | PackageDCPOutputDir= 97 | SearchPath=;C:\DelphiTools\TeeChart.v8.01.Full.Source.Delphi.BCB.BDS.CRS.ccrun.776754\Sources\Compiled\Delphi7\Lib 98 | Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;TMSD7;tmsexd7;tmswizd7;tmsxlsd7;RaizeComponentsVcl;RaizeComponentsVclDb;Tee87;TeeUI87;TeeDB87;TeePro87;TeeGL87;TeeImage87;TeeLanguage87;TeeWorld87 99 | Conditionals= 100 | DebugSourceDirs= 101 | UsePackages=0 102 | [Parameters] 103 | RunParams= 104 | HostApplication= 105 | Launcher= 106 | UseLauncher=0 107 | DebugCWD= 108 | [Language] 109 | ActiveLang= 110 | ProjectLang= 111 | RootDir=C:\Program Files\Borland\Delphi7\Bin\ 112 | [Version Info] 113 | IncludeVerInfo=0 114 | AutoIncBuild=0 115 | MajorVer=1 116 | MinorVer=0 117 | Release=0 118 | Build=0 119 | Debug=0 120 | PreRelease=0 121 | Special=0 122 | Private=0 123 | DLL=0 124 | Locale=2052 125 | CodePage=936 126 | [Version Info Keys] 127 | CompanyName= 128 | FileDescription= 129 | FileVersion=1.0.0.0 130 | InternalName= 131 | LegalCopyright= 132 | LegalTrademarks= 133 | OriginalFilename= 134 | ProductName= 135 | ProductVersion=1.0.0.0 136 | Comments= 137 | [Excluded Packages] 138 | c:\program files\borland\delphi7\Bin\dcltee77.bpl=TeeChart Components 139 | c:\program files\borland\delphi7\Bin\dclteepro77.bpl=TeeChart Pro Components 140 | c:\program files\borland\delphi7\Bin\dcltqr77.bpl=TeeChart for QuickReport 141 | c:\program files\borland\delphi7\Bin\dcltgl77.bpl=TeeChart OpenGL 142 | c:\program files\borland\delphi7\Bin\dcltee70.bpl=TeeChart Standard 143 | c:\program files\borland\delphi7\Bin\dcltqr70.bpl=TeeChart for QuickReport 144 | c:\program files\borland\delphi7\Bin\dcltee7100.bpl=TeeChart Components 145 | c:\program files\borland\delphi7\Bin\dcltee67.bpl=TeeChart Components 146 | c:\program files\borland\delphi7\Bin\dclteepro67.bpl=TeeChart Pro Components 147 | c:\program files\borland\delphi7\Bin\dcltqr67.bpl=TeeChart for QuickReport 148 | c:\program files\borland\delphi7\Bin\dcltgl67.bpl=TeeChart OpenGL 149 | c:\program files\borland\delphi7\Bin\dcltee6100.bpl=TeeChart Components 150 | c:\program files\borland\delphi7\Bin\dcltee57.bpl=TeeChart Components 151 | c:\program files\borland\delphi7\Bin\dcltep57.bpl=TeeChart Pro Components 152 | c:\program files\borland\delphi7\Bin\dcltqr57.bpl=TeeChart for QuickReport 153 | c:\program files\borland\delphi7\Bin\dcltgl57.bpl=TeeChart OpenGL 154 | c:\program files\borland\delphi7\Bin\dcltee5100.bpl=TeeChart Components 155 | c:\program files\borland\delphi7\Bin\dcltee47.bpl=TeeChart Components 156 | c:\program files\borland\delphi7\Bin\dcltep47.bpl=TeeChart Pro Components 157 | c:\program files\borland\delphi7\Bin\dcltqr47.bpl=TeeChart for QuickReport 158 | c:\program files\borland\delphi7\Bin\dcltgl47.bpl=TeeChart OpenGL 159 | c:\program files\borland\delphi7\Bin\dcltee4100.bpl=TeeChart Components 160 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTest.dpr: -------------------------------------------------------------------------------- 1 | program HtmlParserTest; 2 | 3 | uses 4 | Forms, 5 | HtmlParserTestMain in 'HtmlParserTestMain.pas' {Form16}, 6 | DOMCore in 'htmlp\DOMCore.pas', 7 | Entities in 'htmlp\Entities.pas', 8 | Formatter in 'htmlp\Formatter.pas', 9 | HTMLParser in 'htmlp\HTMLParser.pas', 10 | HtmlReader in 'htmlp\HtmlReader.pas', 11 | HtmlTags in 'htmlp\HtmlTags.pas', 12 | WStrings in 'htmlp\WStrings.pas'; 13 | 14 | {$R *.res} 15 | 16 | begin 17 | Application.Initialize; 18 | Application.CreateForm(TForm16, Form16); 19 | Application.Run; 20 | end. 21 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTest.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {EC1AC04C-625B-48CB-B12D-AB291F79A569} 4 | 15.4 5 | VCL 6 | HtmlParserTest.dpr 7 | True 8 | Debug 9 | Win32 10 | 1 11 | Application 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Cfg_1 29 | true 30 | true 31 | 32 | 33 | true 34 | Base 35 | true 36 | 37 | 38 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 39 | $(BDS)\bin\default_app.manifest 40 | 2052 41 | $(BDS)\bin\delphi_PROJECTICON.ico 42 | System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) 43 | HtmlParserTest 44 | .\$(Platform)\$(Config) 45 | .\$(Platform)\$(Config) 46 | false 47 | false 48 | false 49 | false 50 | false 51 | 52 | 53 | .\ 54 | true 55 | JvBDE;JvGlobus;UnitSystem;JvMM;TeeGL920;JvManagedThreads;SmartComponents;FireDACSqliteDriver;FireDACDSDriver;DBXSqliteDriver;ZRGraph;ZRLicense;FireDACPgDriver;TeeLanguage920;fmx;RaizeComponentsVcl;IndySystem;JvDlgs;JvCrypt;tethering;TP_LockBox3;NativeXmlPkg;ZRCore;vclib;inetdbbde;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;TeeDB920;JvNet;DataSnapProviderClient;TeeUI920;DBXSybaseASEDriver;JvDotNetCtrls;DbxCommonDriver;vclimg;FmxTeeUI920;dbxcds;DatasnapConnectorsFreePascal;MetropolisUILiveTile;FMXTee920;SynEdit_RXE6;JvXPCtrls;vcldb;vcldsnap;fmxFireDAC;DBXDb2Driver;ColorMapComponents;DBXOracleDriver;CustomIPTransport;JvCore;vclribbon;dsnap;IndyIPServer;FMXTeeLanguage920;fmxase;vcl;IndyCore;tmsxlsdXE6;mbColorLib;DBXMSSQLDriver;CloudService;IndyIPCommon;TsiLang_XE6r;FireDACIBDriver;TeeImage920;DataSnapFireDAC;FireDACDBXDriver;JvAppFrm;soapserver;JvDB;JvRuntimeDesign;inetdbxpress;GLScene_RunTime_VCL;dsnapxml;tmsdXE6;FireDACInfxDriver;FireDACDb2Driver;JclDeveloperTools;ALGLIB;JvDocking;adortl;FMXTeePro920;TeePro920;JvWizards;madBasic_;FireDACASADriver;JvHMI;TeeMaker120;TeeTree2D20Tee9;bindcompfmx;JvBands;vcldbx;RaizeComponentsVclDb;FireDACODBCDriver;RESTBackendComponents;rtl;dbrtl;DbxClientDriver;SmartStorage;FireDACCommon;bindcomp;inetdb;JvPluginSystem;JclContainers;DBXOdbcDriver;JvCmp;vclFireDAC;madDisAsm_;AlgorithmProvider;JvSystem;xmlrtl;DataSnapNativeClient;ibxpress;svnui;JvControls;Tee920;JvTimeFramework;IndyProtocols;DBXMySQLDriver;FMXTeeDB920;FireDACCommonDriver;MIT3DPkg;tmswizdXE6;bindcompdbx;bindengine;vclactnband;soaprtl;JvJans;JvPageComps;bindcompvcl;JvStdCtrls;JvCustom;Jcl;vclie;JvPrintPreview;ZRComponnets;ZRZonationModel;madExcept_;FireDACADSDriver;vcltouch;ZRRockyModel;GraphPackage;PngComponents;VCLRESTComponents;FireDAC;DBXInformixDriver;FireDACMSSQLDriver;Intraweb;VclSmp;TeeWorld920;DataSnapConnectors;DataSnapServerMidas;DBXFirebirdDriver;dsnapcon;inet;fmxobj;JclVcl;JvPascalInterpreter;FireDACMySQLDriver;soapmidas;vclx;tmsexdXE6;ZRLithPack;svn;DBXSybaseASADriver;FireDACOracleDriver;fmxdae;RESTComponents;bdertl;GdiPlus;dbexpress;FireDACMSAccDriver;DataSnapIndy10ServerTransport;IndyIPClient;$(DCC_UsePackage) 56 | 1033 57 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 58 | 59 | 60 | DEBUG;$(DCC_Define) 61 | true 62 | false 63 | true 64 | true 65 | true 66 | 67 | 68 | 1033 69 | true 70 | false 71 | 72 | 73 | false 74 | RELEASE;$(DCC_Define) 75 | 0 76 | 0 77 | 78 | 79 | 80 | MainSource 81 | 82 | 83 |
Form16
84 | dfm 85 |
86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | Cfg_2 96 | Base 97 | 98 | 99 | Base 100 | 101 | 102 | Cfg_1 103 | Base 104 | 105 |
106 | 107 | Delphi.Personality.12 108 | 109 | 110 | 111 | 112 | HtmlParserTest.dpr 113 | 114 | 115 | Microsoft Office 2000 Sample Automation Server Wrapper Components 116 | Microsoft Office XP Sample Automation Server Wrapper Components 117 | 118 | 119 | 120 | 121 | True 122 | 123 | 124 | 12 125 | 126 | 127 | 128 |
129 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTest.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/HtmlParserTest_D7/HtmlParserTest.res -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTestMain.dfm: -------------------------------------------------------------------------------- 1 | object Form16: TForm16 2 | Left = 311 3 | Top = 238 4 | Width = 857 5 | Height = 332 6 | Caption = 'Html Parser Test' 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | DesignSize = ( 15 | 849 16 | 298) 17 | PixelsPerInch = 96 18 | TextHeight = 13 19 | object btn1: TButton 20 | Left = 749 21 | Top = 8 22 | Width = 75 23 | Height = 25 24 | Anchors = [akTop, akRight] 25 | Caption = 'Parse' 26 | TabOrder = 0 27 | OnClick = btn1Click 28 | end 29 | object lv1: TListView 30 | Left = 8 31 | Top = 8 32 | Width = 735 33 | Height = 281 34 | Anchors = [akLeft, akTop, akRight, akBottom] 35 | Columns = < 36 | item 37 | Caption = 'href' 38 | Width = 240 39 | end 40 | item 41 | Caption = 'Content' 42 | Width = 240 43 | end 44 | item 45 | Caption = 'Date' 46 | Width = 120 47 | end> 48 | ReadOnly = True 49 | TabOrder = 1 50 | ViewStyle = vsReport 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/HtmlParserTestMain.pas: -------------------------------------------------------------------------------- 1 | unit HtmlParserTestMain; 2 | 3 | interface 4 | 5 | uses 6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, 7 | Controls, Forms, Dialogs, StdCtrls, 8 | HTMLParser, Grids, ComCtrls; 9 | 10 | type 11 | TForm16 = class(TForm) 12 | btn1: TButton; 13 | lv1: TListView; 14 | procedure btn1Click(Sender: TObject); 15 | private 16 | { Private declarations } 17 | HtmlParser: THtmlParser; 18 | function LoadHtmlFile: WideString; 19 | public 20 | { Public declarations } 21 | end; 22 | 23 | var 24 | Form16: TForm16; 25 | 26 | implementation 27 | 28 | uses 29 | DomCore, Formatter; 30 | 31 | {$R *.dfm} 32 | 33 | procedure TForm16.btn1Click(Sender: TObject); 34 | var 35 | HtmlDoc: TDocument; 36 | Formatter: TBaseFormatter; 37 | list: TNodeList; 38 | I: Integer; 39 | span: TNode; 40 | classAttr: TNode; 41 | href: TNode; 42 | Item: TListItem; 43 | begin 44 | HtmlParser := THtmlParser.Create; 45 | try 46 | try 47 | HtmlDoc := HtmlParser.parseString(LoadHtmlFile); 48 | except 49 | end; 50 | list := HtmlDoc.getElementsByTagName('span'); 51 | for I := 0 to list.length-1 do 52 | begin 53 | span := list.item(i); 54 | classAttr := span.attributes.getNamedItem('class'); 55 | if Assigned(classAttr) then 56 | begin 57 | if classAttr.childNodes.item(0).NodeValue = 'ina_zh' then 58 | begin 59 | href := span.childNodes.item(0); 60 | if href.nodeName = 'a' then 61 | begin 62 | Item := lv1.Items.Add; 63 | Item.Caption := href.attributes.getNamedItem('href').childNodes.item(0).nodeValue; 64 | Item.SubItems.Add(href.childNodes.item(0).NodeValue); 65 | Item.SubItems.Add(span.parentNode.childNodes.item(2).childNodes.item(0).NodeValue); 66 | end; 67 | end; 68 | end; 69 | end; 70 | list.Free; 71 | finally 72 | HtmlParser.Free 73 | end; 74 | 75 | 76 | 77 | HtmlDoc.Free; 78 | 79 | end; 80 | 81 | function TForm16.LoadHtmlFile: WideString; 82 | var 83 | F: TFileStream; 84 | S: AnsiString; 85 | begin 86 | F := TFileStream.Create('Test.html', fmOpenRead); 87 | try 88 | SetLength(S, F.Size); 89 | F.Read(S[1], F.Size); 90 | Result := UTF8Decode(s); 91 | finally 92 | F.Free 93 | end; 94 | end; 95 | 96 | end. 97 | -------------------------------------------------------------------------------- /HtmlParserTest_D7/README.md: -------------------------------------------------------------------------------- 1 | # Html Parser Test for delphi 7 2 | 3 | This Demo use "Delphi Dom HTML Parser and Converter", the original address is: 4 | 5 | http://sourceforge.net/projects/htmlp/ 6 | 7 | This Demo demonstrate how to use HTML Parser parse a HTML file and get information. 8 | 9 | 这个Demo使用了Delphi Dom HTML Parser and Converter,原始的源代码可以到以下地址下载: 10 | 11 | http://sourceforge.net/projects/htmlp/ 12 | 13 | 该Demo演示了使用HTML Parser解析一个HTML文件,并提取其中信息。 -------------------------------------------------------------------------------- /HtmlParserTest_D7/htmlp/HTMLParser.pas: -------------------------------------------------------------------------------- 1 | unit HtmlParser; 2 | 3 | interface 4 | 5 | uses 6 | DomCore, HtmlReader, HtmlTags; 7 | 8 | type 9 | THtmlParser = class 10 | private 11 | FHtmlDocument: TDocument; 12 | FHtmlReader: THtmlReader; 13 | FCurrentNode: TNode; 14 | FCurrentTag: THtmlTag; 15 | function FindDefParent: TElement; 16 | function FindParent: TElement; 17 | function FindParentElement(tagList: THtmlTagSet): TElement; 18 | function FindTableParent: TElement; 19 | function FindThisElement: TElement; 20 | function GetMainElement(const tagName: TDomString): TElement; 21 | procedure ProcessAttributeEnd(Sender: TObject); 22 | procedure ProcessAttributeStart(Sender: TObject); 23 | procedure ProcessCDataSection(Sender: TObject); 24 | procedure ProcessComment(Sender: TObject); 25 | procedure ProcessDocType(Sender: TObject); 26 | procedure ProcessElementEnd(Sender: TObject); 27 | procedure ProcessElementStart(Sender: TObject); 28 | procedure ProcessEndElement(Sender: TObject); 29 | procedure ProcessEntityReference(Sender: TObject); 30 | procedure ProcessTextNode(Sender: TObject); 31 | public 32 | constructor Create; 33 | destructor Destroy; override; 34 | function parseString(const htmlStr: TDomString): TDocument; 35 | property HtmlDocument: TDocument read FHtmlDocument; 36 | end; 37 | 38 | implementation 39 | 40 | const 41 | htmlTagName = 'html'; 42 | headTagName = 'head'; 43 | bodyTagName = 'body'; 44 | 45 | constructor THtmlParser.Create; 46 | begin 47 | inherited Create; 48 | FHtmlReader := THtmlReader.Create; 49 | with FHtmlReader do 50 | begin 51 | OnAttributeEnd := ProcessAttributeEnd; 52 | OnAttributeStart := ProcessAttributeStart; 53 | OnCDataSection := ProcessCDataSection; 54 | OnComment := ProcessComment; 55 | OnDocType := ProcessDocType; 56 | OnElementEnd := ProcessElementEnd; 57 | OnElementStart := ProcessElementStart; 58 | OnEndElement := ProcessEndElement; 59 | OnEntityReference := ProcessEntityReference; 60 | //OnNotation := ProcessNotation; 61 | //OnProcessingInstruction := ProcessProcessingInstruction; 62 | OnTextNode := ProcessTextNode; 63 | end 64 | end; 65 | 66 | destructor THtmlParser.Destroy; 67 | begin 68 | FHtmlReader.Free; 69 | inherited Destroy 70 | end; 71 | 72 | function THtmlParser.FindDefParent: TElement; 73 | begin 74 | if FCurrentTag.Number in [HEAD_TAG, BODY_TAG] then 75 | Result := FHtmlDocument.appendChild(FHtmlDocument.createElement(htmlTagName)) as TElement 76 | else 77 | if FCurrentTag.Number in HeadTags then 78 | Result := GetMainElement(headTagName) 79 | else 80 | Result := GetMainElement(bodyTagName) 81 | end; 82 | 83 | function THtmlParser.FindParent: TElement; 84 | begin 85 | if (FCurrentTag.Number = P_TAG) or (FCurrentTag.Number in BlockTags) then 86 | Result := FindParentElement(BlockParentTags) 87 | else 88 | if FCurrentTag.Number = LI_TAG then 89 | Result := FindParentElement(ListItemParentTags) 90 | else 91 | if FCurrentTag.Number in [DD_TAG, DT_TAG] then 92 | Result := FindParentElement(DefItemParentTags) 93 | else 94 | if FCurrentTag.Number in [TD_TAG, TH_TAG] then 95 | Result := FindParentElement(CellParentTags) 96 | else 97 | if FCurrentTag.Number = TR_TAG then 98 | Result := FindParentElement(RowParentTags) 99 | else 100 | if FCurrentTag.Number = COL_TAG then 101 | Result := FindParentElement(ColParentTags) 102 | else 103 | if FCurrentTag.Number in [COLGROUP_TAG, THEAD_TAG, TFOOT_TAG, TBODY_TAG] then 104 | Result := FindParentElement(TableSectionParentTags) 105 | else 106 | if FCurrentTag.Number = TABLE_TAG then 107 | Result := FindTableParent 108 | else 109 | if FCurrentTag.Number = OPTION_TAG then 110 | Result := FindParentElement(OptionParentTags) 111 | else 112 | if FCurrentTag.Number in [HEAD_TAG, BODY_TAG] then 113 | Result := FHtmlDocument.documentElement as TElement 114 | else 115 | Result := nil; 116 | if Result = nil then 117 | Result := FindDefParent 118 | end; 119 | 120 | function THtmlParser.FindParentElement(tagList: THtmlTagSet): TElement; 121 | var 122 | Node: TNode; 123 | HtmlTag: THtmlTag; 124 | begin 125 | Node := FCurrentNode; 126 | while Node.nodeType = ELEMENT_NODE do 127 | begin 128 | HtmlTag := HtmlTagList.GetTagByName(Node.nodeName); 129 | if HtmlTag.Number in tagList then 130 | begin 131 | Result := Node as TElement; 132 | Exit 133 | end; 134 | Node := Node.parentNode 135 | end; 136 | Result := nil 137 | end; 138 | 139 | function THtmlParser.FindTableParent: TElement; 140 | var 141 | Node: TNode; 142 | HtmlTag: THtmlTag; 143 | begin 144 | Node := FCurrentNode; 145 | while Node.nodeType = ELEMENT_NODE do 146 | begin 147 | HtmlTag := HtmlTagList.GetTagByName(Node.nodeName); 148 | if (HtmlTag.Number = TD_TAG) or (HtmlTag.Number in BlockTags) then 149 | begin 150 | Result := Node as TElement; 151 | Exit 152 | end; 153 | Node := Node.parentNode 154 | end; 155 | Result := GetMainElement(bodyTagName) 156 | end; 157 | 158 | function THtmlParser.FindThisElement: TElement; 159 | var 160 | Node: TNode; 161 | begin 162 | Node := FCurrentNode; 163 | while Node.nodeType = ELEMENT_NODE do 164 | begin 165 | Result := Node as TElement; 166 | if Result.tagName = FHtmlReader.nodeName then 167 | Exit; 168 | Node := Node.parentNode 169 | end; 170 | Result := nil 171 | end; 172 | 173 | function THtmlParser.GetMainElement(const tagName: TDomString): TElement; 174 | var 175 | child: TNode; 176 | I: Integer; 177 | begin 178 | if FHtmlDocument.documentElement = nil then 179 | FHtmlDocument.appendChild(FHtmlDocument.createElement(htmlTagName)); 180 | for I := 0 to FHtmlDocument.documentElement.childNodes.length - 1 do 181 | begin 182 | child := FHtmlDocument.documentElement.childNodes.item(I); 183 | if (child.nodeType = ELEMENT_NODE) and (child.nodeName = tagName) then 184 | begin 185 | Result := child as TElement; 186 | Exit 187 | end 188 | end; 189 | Result := FHtmlDocument.createElement(tagName); 190 | FHtmlDocument.documentElement.appendChild(Result) 191 | end; 192 | 193 | procedure THtmlParser.ProcessAttributeEnd(Sender: TObject); 194 | begin 195 | FCurrentNode := (FCurrentNode as TAttr).ownerElement 196 | end; 197 | 198 | procedure THtmlParser.ProcessAttributeStart(Sender: TObject); 199 | var 200 | Attr: TAttr; 201 | begin 202 | Attr := FHtmlDocument.createAttribute((Sender as THtmlReader).nodeName); 203 | (FCurrentNode as TElement).setAttributeNode(Attr); 204 | FCurrentNode := Attr 205 | end; 206 | 207 | procedure THtmlParser.ProcessCDataSection(Sender: TObject); 208 | var 209 | CDataSection: TCDataSection; 210 | begin 211 | CDataSection := FHtmlDocument.createCDATASection(FHtmlReader.nodeValue); 212 | FCurrentNode.appendChild(CDataSection) 213 | end; 214 | 215 | procedure THtmlParser.ProcessComment(Sender: TObject); 216 | var 217 | Comment: TComment; 218 | begin 219 | Comment := FHtmlDocument.createComment(FHtmlReader.nodeValue); 220 | FCurrentNode.appendChild(Comment) 221 | end; 222 | 223 | procedure THtmlParser.ProcessDocType(Sender: TObject); 224 | begin 225 | with FHtmlReader do 226 | FHtmlDocument.docType := DomImplementation.createDocumentType(nodeName, publicID, systemID); 227 | end; 228 | 229 | procedure THtmlParser.ProcessElementEnd(Sender: TObject); 230 | begin 231 | if FHtmlReader.isEmptyElement or (FCurrentTag.Number in EmptyTags) then 232 | FCurrentNode := FCurrentNode.parentNode; 233 | FCurrentTag := nil 234 | end; 235 | 236 | procedure THtmlParser.ProcessElementStart(Sender: TObject); 237 | var 238 | Element: TElement; 239 | Parent: TNode; 240 | begin 241 | FCurrentTag := HtmlTagList.GetTagByName(FHtmlReader.nodeName); 242 | if FCurrentTag.Number in NeedFindParentTags + BlockTags then 243 | begin 244 | Parent := FindParent; 245 | if not Assigned(Parent) then 246 | raise DomException.Create(HIERARCHY_REQUEST_ERR); 247 | FCurrentNode := Parent 248 | end; 249 | Element := FHtmlDocument.createElement(FHtmlReader.nodeName); 250 | FCurrentNode.appendChild(Element); 251 | FCurrentNode := Element 252 | end; 253 | 254 | procedure THtmlParser.ProcessEndElement(Sender: TObject); 255 | var 256 | Element: TElement; 257 | begin 258 | Element := FindThisElement; 259 | if Assigned(Element) then 260 | FCurrentNode := Element.parentNode 261 | { else 262 | if IsBlockTagName(FHtmlReader.nodeName) then 263 | raise DomException.Create(HIERARCHY_REQUEST_ERR)} 264 | end; 265 | 266 | procedure THtmlParser.ProcessEntityReference(Sender: TObject); 267 | var 268 | EntityReference: TEntityReference; 269 | begin 270 | EntityReference := FHtmlDocument.createEntityReference(FHtmlReader.nodeName); 271 | FCurrentNode.appendChild(EntityReference) 272 | end; 273 | 274 | procedure THtmlParser.ProcessTextNode(Sender: TObject); 275 | var 276 | TextNode: TTextNode; 277 | begin 278 | TextNode := FHtmlDocument.createTextNode(FHtmlReader.nodeValue); 279 | FCurrentNode.appendChild(TextNode) 280 | end; 281 | 282 | function THtmlParser.parseString(const htmlStr: TDomString): TDocument; 283 | begin 284 | FHtmlReader.htmlStr := htmlStr; 285 | FHtmlDocument := DomImplementation.createEmptyDocument(nil); 286 | FCurrentNode := FHtmlDocument; 287 | try 288 | while FHtmlReader.Read do; 289 | except 290 | // TODO: Add event ? 291 | end; 292 | Result := FHtmlDocument 293 | end; 294 | 295 | end. 296 | -------------------------------------------------------------------------------- /LoadCustomCursor/CursorTest.dfm: -------------------------------------------------------------------------------- 1 | object LoadCursorTestForm: TLoadCursorTestForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'Load Custom Cursor Test' 5 | ClientHeight = 452 6 | ClientWidth = 562 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | OnCreate = FormCreate 15 | PixelsPerInch = 96 16 | TextHeight = 13 17 | object pnlCanvas: TPaintBox 18 | Left = 70 19 | Top = 75 20 | Width = 404 21 | Height = 305 22 | OnMouseMove = pnlCanvasMouseMove 23 | OnPaint = pnlCanvasPaint 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /LoadCustomCursor/CursorTest.pas: -------------------------------------------------------------------------------- 1 | unit CursorTest; 2 | 3 | interface 4 | 5 | uses 6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 7 | Dialogs, ExtCtrls; 8 | 9 | const 10 | cr5 = 5; 11 | cr6 = 6; 12 | cr7 = 7; 13 | cr8 = 8; 14 | cr9 = 9; 15 | cr10 = 10; 16 | 17 | type 18 | TLoadCursorTestForm = class(TForm) 19 | pnlCanvas: TPaintBox; 20 | procedure pnlCanvasPaint(Sender: TObject); 21 | procedure FormCreate(Sender: TObject); 22 | procedure pnlCanvasMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 23 | private 24 | { Private declarations } 25 | public 26 | { Public declarations } 27 | end; 28 | 29 | var 30 | LoadCursorTestForm: TLoadCursorTestForm; 31 | 32 | implementation 33 | 34 | {$R *.dfm} 35 | 36 | procedure TLoadCursorTestForm.FormCreate(Sender: TObject); 37 | begin 38 | screen.cursors[cr5] := LoadCursor(hInstance, pChar('Cursor_Move')); 39 | end; 40 | 41 | procedure TLoadCursorTestForm.pnlCanvasMouseMove(Sender: TObject; Shift: TShiftState; X, 42 | Y: Integer); 43 | begin 44 | if PtInRect(Rect(100,100,200,200), Point(x,y)) then 45 | Screen.Cursor := cr5 46 | else 47 | Screen.Cursor := crDefault; 48 | end; 49 | 50 | procedure TLoadCursorTestForm.pnlCanvasPaint(Sender: TObject); 51 | begin 52 | pnlCanvas.Canvas.Rectangle(Rect(100,100,200,200)); 53 | end; 54 | 55 | end. 56 | -------------------------------------------------------------------------------- /LoadCustomCursor/LoadCustomCursor.dpr: -------------------------------------------------------------------------------- 1 | program LoadCustomCursor; 2 | 3 | 4 | 5 | {$R *.dres} 6 | 7 | uses 8 | Forms, 9 | CursorTest in 'CursorTest.pas' {LoadCursorTestForm}; 10 | 11 | {$R *.res} 12 | 13 | begin 14 | Application.Initialize; 15 | Application.MainFormOnTaskbar := True; 16 | Application.CreateForm(TLoadCursorTestForm, LoadCursorTestForm); 17 | Application.Run; 18 | end. 19 | -------------------------------------------------------------------------------- /LoadCustomCursor/Move.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/LoadCustomCursor/Move.cur -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DelphiDemos 2 | 3 | 4 | ZXingScanDemo 是使用ZXing.Delphi扫描的一个demo,与原有的demo相比,增加了一些优化和辅助的美化,使用这个Demo,需要自己下载ZXing.Delphi,https://github.com/Spelt/ZXing.Delphi 5 | 6 | ScanCodeDemo 相比ZXingScanDemo,对相机的聚焦(安卓)和性能进行了优化 7 | 8 | 9 | [捐助名单](DonationList.md) 10 | 11 | 12 | #关于捐助: 13 | 14 | 本项目所有示例均可免费下载和使用,无需通知我, 15 | 如果你觉得本项目的示例对你有所帮助而你刚好又想对本项目进行捐助,请联系作者:QQ 21114963 16 | 17 | 18 | # Site Links 19 | 20 | ## [learndelphi](//learndelphi.org) 21 | 22 | ## [embarcadero](//embarcadero.com) 23 | -------------------------------------------------------------------------------- /Recorder/RecorderDemo.dpr: -------------------------------------------------------------------------------- 1 | program RecorderDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | RecorderDemoMain in 'RecorderDemoMain.pas' {RecorderdDemoForm}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TRecorderdDemoForm, RecorderdDemoForm); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Recorder/RecorderDemo.dproj.local: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2016/06/21 15:47:36.990,=C:\Users\zhaoyp\Documents\Embarcadero\Studio\Projects\Unit33.pas 5 | 2016/06/21 15:49:22.096,E:\Develop\Delphi\Group\DelphiDemos\Recorder\RecorderDemoMain.pas=C:\Users\zhaoyp\Documents\Embarcadero\Studio\Projects\Unit33.pas 6 | 2016/06/21 15:49:22.096,E:\Develop\Delphi\Group\DelphiDemos\Recorder\RecorderDemoMain.fmx=C:\Users\zhaoyp\Documents\Embarcadero\Studio\Projects\Unit33.fmx 7 | 2016/06/21 16:05:25.352,E:\Develop\Delphi\Group\DelphiDemos\Recorder\RecorderDemo.dproj=C:\Users\zhaoyp\Documents\Embarcadero\Studio\Projects\Project27.dproj 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Recorder/RecorderDemo.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/Recorder/RecorderDemo.res -------------------------------------------------------------------------------- /Recorder/RecorderDemoMain.fmx: -------------------------------------------------------------------------------- 1 | object RecorderdDemoForm: TRecorderdDemoForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form33' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnCreate = FormCreate 11 | DesignerMasterStyle = 0 12 | object Button2: TButton 13 | Action = acPlay 14 | Enabled = True 15 | ImageIndex = -1 16 | Position.X = 280.000000000000000000 17 | Position.Y = 232.000000000000000000 18 | TabOrder = 5 19 | Visible = True 20 | end 21 | object Button3: TButton 22 | Action = acStop 23 | Enabled = True 24 | ImageIndex = -1 25 | Position.X = 280.000000000000000000 26 | Position.Y = 264.000000000000000000 27 | TabOrder = 4 28 | Visible = True 29 | end 30 | object Button4: TButton 31 | Action = acStartRecording 32 | Enabled = True 33 | ImageIndex = -1 34 | Position.X = 280.000000000000000000 35 | Position.Y = 296.000000000000000000 36 | TabOrder = 3 37 | Visible = True 38 | end 39 | object Button5: TButton 40 | Action = acStopRecording 41 | Enabled = True 42 | ImageIndex = -1 43 | Position.X = 280.000000000000000000 44 | Position.Y = 328.000000000000000000 45 | TabOrder = 2 46 | Visible = True 47 | OnClick = Button5Click 48 | end 49 | object Label1: TLabel 50 | Position.X = 136.000000000000000000 51 | Position.Y = 136.000000000000000000 52 | Text = 'Label1' 53 | end 54 | object Label2: TLabel 55 | Position.X = 136.000000000000000000 56 | Position.Y = 176.000000000000000000 57 | Text = 'Label1' 58 | end 59 | object ActionList1: TActionList 60 | OnUpdate = ActionList1Update 61 | Left = 328 62 | Top = 80 63 | object acStartRecording: TAction 64 | Text = #24320#22987#24405#38899 65 | OnExecute = acStartRecordingExecute 66 | end 67 | object acStopRecording: TAction 68 | Text = #20572#27490#24405#38899 69 | end 70 | object acPlay: TAction 71 | Text = 'acPlay' 72 | OnExecute = acPlayExecute 73 | end 74 | object acStop: TAction 75 | Text = 'acStop' 76 | OnExecute = acStopExecute 77 | end 78 | end 79 | object MediaPlayer1: TMediaPlayer 80 | Left = 112 81 | Top = 248 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /Recorder/RecorderDemoMain.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/Recorder/RecorderDemoMain.pas -------------------------------------------------------------------------------- /RoundImageDemo/DemoImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/RoundImageDemo/DemoImage.png -------------------------------------------------------------------------------- /RoundImageDemo/RoundImageDemo.dpr: -------------------------------------------------------------------------------- 1 | program RoundImageDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | RoundImageForm in 'RoundImageForm.pas' {Form11}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm11, Form11); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /RoundImageDemo/RoundImageDemo.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/RoundImageDemo/RoundImageDemo.res -------------------------------------------------------------------------------- /RoundImageDemo/RoundImageForm.fmx: -------------------------------------------------------------------------------- 1 | object Form11: TForm11 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form11' 5 | ClientHeight = 250 6 | ClientWidth = 385 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object Image1: TImage 12 | MultiResBitmap = < 13 | item 14 | end> 15 | Position.X = 32.000000000000000000 16 | Position.Y = 32.000000000000000000 17 | Size.Width = 161.000000000000000000 18 | Size.Height = 153.000000000000000000 19 | Size.PlatformDefault = False 20 | end 21 | object Button1: TButton 22 | Position.X = 208.000000000000000000 23 | Position.Y = 80.000000000000000000 24 | Size.Width = 169.000000000000000000 25 | Size.Height = 41.000000000000000000 26 | Size.PlatformDefault = False 27 | TabOrder = 1 28 | Text = 'Show RoundRect Image' 29 | OnClick = Button1Click 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /RoundImageDemo/RoundImageForm.pas: -------------------------------------------------------------------------------- 1 | unit RoundImageForm; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, 8 | FMX.Controls.Presentation, FMX.StdCtrls; 9 | 10 | type 11 | TForm11 = class(TForm) 12 | Image1: TImage; 13 | Button1: TButton; 14 | procedure Button1Click(Sender: TObject); 15 | private 16 | { Private declarations } 17 | public 18 | { Public declarations } 19 | end; 20 | 21 | var 22 | Form11: TForm11; 23 | 24 | implementation 25 | 26 | {$R *.fmx} 27 | 28 | procedure TForm11.Button1Click(Sender: TObject); 29 | var 30 | B1, B2: TBitmap; 31 | begin 32 | B1 := TBitmap.Create; 33 | B1.LoadFromFile('..\..\DemoImage.png'); 34 | B2 := TBitmap.Create(B1.Width, B1.Height); 35 | try 36 | B2.Clear(0); 37 | B2.Canvas.BeginScene; 38 | B2.Canvas.Fill.Bitmap.Bitmap := B1; 39 | B2.Canvas.Fill.Bitmap.WrapMode := TWrapMode.TileStretch; 40 | B2.Canvas.Fill.Kind := TBrushKind.Bitmap; 41 | B2.Canvas.FillRect(RectF(0, 0, B2.Width, B2.Height), 30, 30, AllCorners, 1); 42 | B2.Canvas.EndScene; 43 | Image1.Bitmap.Assign(B2); 44 | finally 45 | B1.Free; 46 | B2.Free; 47 | end; 48 | end; 49 | 50 | end. 51 | -------------------------------------------------------------------------------- /ScanCodeDemo/AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | <%uses-permission%> 12 | 13 | 21 | 22 | <%application-meta-data%> 23 | 25 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | <%activity%> 38 | 39 | <%receivers%> 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ScanCodeDemo/Entitlement.TemplateiOS.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%getTaskAllowKey%> 6 | <%applicationIdentifier%> 7 | <%pushNotificationKey%> 8 | <%keychainAccessGroups%> 9 | 10 | 11 | -------------------------------------------------------------------------------- /ScanCodeDemo/Fast/FastUtils.pas: -------------------------------------------------------------------------------- 1 | unit FastUtils; 2 | { Optimized Delphi routines for RGBA<>BGRA conversion, YV12>RGBA conversion and 3 | bitmap rotation } 4 | 5 | interface 6 | 7 | { Swaps the Red and Blue components of pixels in a memory buffer. 8 | 9 | Parameters: 10 | ASrc: points to the source buffer containing the pixels to convert. 11 | ADst: points to the destination buffer for the converted pixels. May be 12 | the same as ASrc. 13 | APixelCount: the number of pixels to convert. 14 | 15 | The Src and Dst buffers must have room for at least PixelCount * 4 bytes. } 16 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 17 | 18 | { Converts a buffer from YV12 format to RGBA format. 19 | 20 | Parameters: 21 | AYPtr: pointer to the source Y (luminance) plane 22 | AUPtr: pointer to the source U (chrominance) plane 23 | AVPtr: pointer to the source V (chrominance) plane 24 | ARGBAPtr: pointer to the target interleaved RGBA buffer 25 | AYStride: number of bytes between two rows in the Y plane 26 | AUVStride: number of bytes between two rows in the U and V planes 27 | ARGBAStride: number of bytes between two rows in the RGBA buffer 28 | AWidth: width of the image to convert (must be even). 29 | AHeight: height of the image to convert (must be even). 30 | 31 | The buffers must be large enough to accomodate AWidth * AHeight pixels in 32 | their corresponding format. 33 | 34 | The alpha values will be set to $FF (opaque) 35 | 36 | NOTE: Currently, this procedure only works when AWidth is a multiple of 16 and 37 | AHeight is a multiple of 2. If this is not the case, then some rightmost and 38 | bottommost pixels will not get converted. } 39 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 40 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 41 | 42 | { Rotates a 32-bit bitmap 0, 90, 180 or 270 degrees. 43 | 44 | Parameters: 45 | ASrc: pointer to the source bitmap data 46 | ADst: pointer to the target bitmap data. This must be different than ASrc. 47 | The ASrc and ADst buffers may not share any data. 48 | ASrcWidth: width of the source bitmap (must be a multiple of 4) 49 | ASrcHeight: height of the source bitmap (must be a multiple of 4) 50 | AAngle: the angle of rotation (0, 90, 180 or 270) 51 | 52 | When rotating 0 or 180 degrees, the dimensions of ADst must match the 53 | dimensions of ASrc. When rotating 90 or 270 degrees, the width of ASrc must 54 | match the height of ADst and the height of ASrc must match the width of ADst. 55 | 56 | Furthermore, this routine expects the dimensions to be a multiple of 4. If 57 | not, an assertion will be raised and the results may be unpredictable. } 58 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 59 | ASrcHeight: Integer; const AAngle: Integer); 60 | 61 | implementation 62 | 63 | uses 64 | System.UITypes; 65 | 66 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 67 | var 68 | I: Integer; 69 | S, D: PAlphaColorRec; 70 | Temp: Byte; 71 | begin 72 | if (ASrc = ADst) then 73 | begin 74 | D := ADst; 75 | for I := 0 to APixelCount - 1 do 76 | begin 77 | Temp := D.B; 78 | D.B := D.R; 79 | D.R := Temp; 80 | Inc(D); 81 | end; 82 | end 83 | else 84 | begin 85 | S := ASrc; 86 | D := ADst; 87 | for I := 0 to APixelCount - 1 do 88 | begin 89 | D.B := S.R; 90 | D.G := S.G; 91 | D.R := S.B; 92 | D.A := S.A; 93 | Inc(S); 94 | Inc(D); 95 | end; 96 | end; 97 | end; 98 | 99 | const 100 | SHIFT = 6; 101 | MAX_VAL = (256 shl SHIFT) - 1; 102 | 103 | function Clip(const AValue: Integer): Integer; inline; 104 | begin 105 | if (AValue < 0) then 106 | Result := 0 107 | else if (AValue > MAX_VAL) then 108 | Result := MAX_VAL 109 | else 110 | Result := AValue; 111 | end; 112 | 113 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 114 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 115 | { This version uses relative low-precision 2.6 integer arithmetic to match the 116 | NEON version. 117 | 118 | Formulas: 119 | R := 1.164*(Y-16) + 1.596*(V-128) 120 | G := 1.164*(Y-16) - 0.391*(U-128) - 0.813*(V-128) 121 | B := 1.164*(Y-16) + 2.018*(U-128) 122 | 123 | We use 2.6 integer arithmetic, so the formulas become: 124 | R := (74*(Y-16) + 102*(V-128)) shr 6 125 | G := (74*(Y-16) - 25*(U-128) - 52*(V-128)) shr 6 126 | B := (74*(Y-16) + 129*(U-128) ) shr 6 127 | 128 | NOTE: we use "127*(U-128)" instead of "129*(U-128)" to match the ARM SIMD 129 | version. } 130 | const 131 | Y_BIAS = 16; 132 | UV_BIAS = 128; 133 | 134 | U_TO_G = 25; 135 | U_TO_B = 127; // Should be 129 136 | V_TO_R = 102; 137 | V_TO_G = 52; 138 | Y_TO_RGB = 74; 139 | 140 | R_INDEX = 0; 141 | G_INDEX = 1; 142 | B_INDEX = 2; 143 | A_INDEX = 3; 144 | var 145 | PaddedWidth, RGBAExtra, YExtra, UVExtra, Row, Col, Y, U, V: Integer; 146 | VtoR, UtoB, UVtoG: Integer; 147 | YPtr, UPtr, VPtr, RGBA: PByte; 148 | begin 149 | if (AWidth <= 0) or (AHeight <= 0) then 150 | Exit; 151 | 152 | Assert(Assigned(AYPtr)); 153 | Assert(Assigned(AUPtr)); 154 | Assert(Assigned(AVPtr)); 155 | Assert(Assigned(ARGBAPtr)); 156 | Assert(AYStride > 0); 157 | Assert(AUVStride > 0); 158 | Assert(ARGBAStride > 0); 159 | Assert((AWidth and 1) = 0); 160 | Assert((AHeight and 1) = 0); 161 | 162 | PaddedWidth := (AWidth + 1) and (not 1); 163 | RGBAExtra := (ARGBAStride - (4 * PaddedWidth)) + ARGBAStride; 164 | YExtra := (AYStride - PaddedWidth) + AYStride; 165 | UVExtra := AUVStride - (PaddedWidth shr 1); 166 | 167 | YPtr := AYPtr; 168 | UPtr := AUPtr; 169 | VPtr := AVPtr; 170 | RGBA := ARGBAPtr; 171 | 172 | Row := 0; 173 | while (Row < AHeight) do 174 | begin 175 | Col := 0; 176 | while (Col < AWidth) do 177 | begin 178 | U := UPtr[0] - UV_BIAS; 179 | V := VPtr[0] - UV_BIAS; 180 | 181 | VtoR := V_TO_R * V; 182 | UVtoG := (U_TO_G * U) + (V_TO_G * V); 183 | UtoB := U_TO_B * U; 184 | 185 | Y := (YPtr[0] - Y_BIAS) * Y_TO_RGB; 186 | RGBA[R_INDEX] := Clip(Y + VtoR) shr SHIFT; 187 | RGBA[G_INDEX] := Clip(Y - UVtoG) shr SHIFT; 188 | RGBA[B_INDEX] := Clip(Y + UtoB) shr SHIFT; 189 | RGBA[A_INDEX] := $FF; 190 | 191 | Y := (YPtr[1] - Y_BIAS) * Y_TO_RGB; 192 | RGBA[R_INDEX + 4] := Clip(Y + VtoR) shr SHIFT; 193 | RGBA[G_INDEX + 4] := Clip(Y - UVtoG) shr SHIFT; 194 | RGBA[B_INDEX + 4] := Clip(Y + UtoB) shr SHIFT; 195 | RGBA[A_INDEX + 4] := $FF; 196 | 197 | Y := (YPtr[AYStride] - Y_BIAS) * Y_TO_RGB; 198 | RGBA[ARGBAStride + R_INDEX] := Clip(Y + VtoR) shr SHIFT; 199 | RGBA[ARGBAStride + G_INDEX] := Clip(Y - UVtoG) shr SHIFT; 200 | RGBA[ARGBAStride + B_INDEX] := Clip(Y + UtoB) shr SHIFT; 201 | RGBA[ARGBAStride + A_INDEX] := $FF; 202 | 203 | Y := (YPtr[AYStride + 1] - Y_BIAS) * Y_TO_RGB; 204 | RGBA[ARGBAStride + R_INDEX + 4] := Clip(Y + VtoR) shr SHIFT; 205 | RGBA[ARGBAStride + G_INDEX + 4] := Clip(Y - UVtoG) shr SHIFT; 206 | RGBA[ARGBAStride + B_INDEX + 4] := Clip(Y + UtoB) shr SHIFT; 207 | RGBA[ARGBAStride + A_INDEX + 4] := $FF; 208 | 209 | Inc(RGBA, 8); 210 | Inc(YPtr, 2); 211 | Inc(UPtr); 212 | Inc(VPtr); 213 | Inc(Col, 2); 214 | end; 215 | Inc(RGBA, RGBAExtra); 216 | Inc(YPtr, YExtra); 217 | Inc(UPtr, UVExtra); 218 | Inc(VPtr, UVExtra); 219 | Inc(Row, 2); 220 | end; 221 | end; 222 | 223 | procedure RotateBitmap0Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 224 | ASrcHeight: Integer); 225 | begin 226 | Move(ASrc^, ADst^, ASrcWidth * ASrcHeight * 4); 227 | end; 228 | 229 | procedure RotateBitmap90Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 230 | ASrcHeight: Integer); 231 | var 232 | S, D: PCardinal; 233 | DstX, DstY, DstDelta: Integer; 234 | begin 235 | S := ASrc; 236 | D := ADst; 237 | Inc(D, ASrcHeight - 1); 238 | 239 | DstDelta := (ASrcWidth * ASrcHeight) + 1; 240 | for DstX := 0 to ASrcHeight - 1 do 241 | begin 242 | for DstY := 0 to ASrcWidth - 1 do 243 | begin 244 | D^ := S^; 245 | Inc(S); 246 | Inc(D, ASrcHeight); 247 | end; 248 | Dec(D, DstDelta); 249 | end; 250 | end; 251 | 252 | procedure RotateBitmap180Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 253 | ASrcHeight: Integer); 254 | var 255 | S, D: PCardinal; 256 | I: Integer; 257 | begin 258 | S := ASrc; 259 | D := ADst; 260 | Inc(D, (ASrcWidth * ASrcHeight) - 1); 261 | for I := 0 to (ASrcWidth * ASrcHeight) - 1 do 262 | begin 263 | D^ := S^; 264 | Inc(S); 265 | Dec(D); 266 | end; 267 | end; 268 | 269 | procedure RotateBitmap270Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 270 | ASrcHeight: Integer); 271 | var 272 | S, D: PCardinal; 273 | DstX, DstY, SrcDelta: Integer; 274 | begin 275 | S := ASrc; 276 | D := ADst; 277 | Inc(S, ASrcWidth - 1); 278 | 279 | SrcDelta := (ASrcHeight * ASrcWidth) + 1; 280 | for DstY := 0 to ASrcWidth - 1 do 281 | begin 282 | for DstX := 0 to ASrcHeight - 1 do 283 | begin 284 | D^ := S^; 285 | Inc(S, ASrcWidth); 286 | Inc(D); 287 | end; 288 | Dec(S, SrcDelta); 289 | end; 290 | end; 291 | 292 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 293 | ASrcHeight: Integer; const AAngle: Integer); 294 | begin 295 | if (ASrcWidth <= 0) or (ASrcHeight <= 0) then 296 | Exit; 297 | 298 | Assert(Assigned(ASrc)); 299 | Assert(Assigned(ADst)); 300 | Assert((ASrcHeight and 3) = 0); 301 | Assert((ASrcWidth and 3) = 0); 302 | 303 | case AAngle of 304 | 0: RotateBitmap0Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 305 | 90: RotateBitmap90Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 306 | 180: RotateBitmap180Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 307 | 270: RotateBitmap270Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 308 | else 309 | Assert(False); 310 | end; 311 | end; 312 | 313 | end. 314 | -------------------------------------------------------------------------------- /ScanCodeDemo/QMScanCode.fmx: -------------------------------------------------------------------------------- 1 | object QMScanCodeForm: TQMScanCodeForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form1' 5 | ClientHeight = 562 6 | ClientWidth = 401 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnActivate = FormActivate 11 | OnCreate = FormCreate 12 | OnClose = FormClose 13 | OnDestroy = FormDestroy 14 | OnShow = FormShow 15 | DesignerMasterStyle = 0 16 | object CameraComponent1: TCameraComponent 17 | Kind = BackCamera 18 | OnSampleBufferReady = CameraComponent1SampleBufferReady 19 | Left = 160 20 | Top = 96 21 | end 22 | object pbCamera: TPaintBox 23 | Align = Contents 24 | Size.Width = 401.000000000000000000 25 | Size.Height = 562.000000000000000000 26 | Size.PlatformDefault = False 27 | OnPaint = pbCameraPaint 28 | object lytScanMask: TLayout 29 | Align = Client 30 | Size.Width = 401.000000000000000000 31 | Size.Height = 562.000000000000000000 32 | Size.PlatformDefault = False 33 | OnResize = lytScanMaskResize 34 | object rectTop: TRectangle 35 | Align = Top 36 | Fill.Color = x80000000 37 | Size.Width = 401.000000000000000000 38 | Size.Height = 130.000000000000000000 39 | Size.PlatformDefault = False 40 | Stroke.Kind = None 41 | end 42 | object rectLeft: TRectangle 43 | Align = Left 44 | Fill.Color = x80000000 45 | Position.Y = 130.000000000000000000 46 | Size.Width = 120.000000000000000000 47 | Size.Height = 302.000000000000000000 48 | Size.PlatformDefault = False 49 | Stroke.Kind = None 50 | end 51 | object rectRight: TRectangle 52 | Align = Right 53 | Fill.Color = x80000000 54 | Position.X = 281.000000000000000000 55 | Position.Y = 130.000000000000000000 56 | Size.Width = 120.000000000000000000 57 | Size.Height = 302.000000000000000000 58 | Size.PlatformDefault = False 59 | Stroke.Kind = None 60 | end 61 | object rectBottom: TRectangle 62 | Align = Bottom 63 | Fill.Color = x80000000 64 | Position.Y = 432.000000000000000000 65 | Size.Width = 401.000000000000000000 66 | Size.Height = 130.000000000000000000 67 | Size.PlatformDefault = False 68 | Stroke.Kind = None 69 | object Text1: TText 70 | Align = Top 71 | Margins.Top = 10.000000000000000000 72 | Position.Y = 10.000000000000000000 73 | Size.Width = 401.000000000000000000 74 | Size.Height = 49.000000000000000000 75 | Size.PlatformDefault = False 76 | Text = #23558#20108#32500#30721#25918#20837#26694#20869#65292#21363#21487#33258#21160#25195#25551 77 | TextSettings.Font.Size = 14.000000000000000000 78 | TextSettings.FontColor = claWhite 79 | TextSettings.VertAlign = Leading 80 | end 81 | end 82 | object lytScanWindow: TRectangle 83 | Align = Client 84 | Fill.Kind = None 85 | Size.Width = 161.000000000000000000 86 | Size.Height = 302.000000000000000000 87 | Size.PlatformDefault = False 88 | Stroke.Color = claWhite 89 | object rectIndicator: TRectangle 90 | Fill.Kind = Gradient 91 | Fill.Gradient.Points = < 92 | item 93 | Color = claWhite 94 | Offset = 0.000000000000000000 95 | end 96 | item 97 | Color = claBlue 98 | Offset = 0.180124223232269300 99 | end 100 | item 101 | Color = claBlue 102 | Offset = 0.493788808584213300 103 | end 104 | item 105 | Color = claBlue 106 | Offset = 0.807453393936157200 107 | end 108 | item 109 | Color = claWhite 110 | Offset = 1.000000000000000000 111 | end> 112 | Fill.Gradient.StartPosition.X = 1.000000000000000000 113 | Fill.Gradient.StartPosition.Y = 0.499999970197677600 114 | Fill.Gradient.StopPosition.Y = 0.500000059604644800 115 | Position.X = 10.000000000000000000 116 | Position.Y = 20.000000000000000000 117 | Size.Width = 120.000000000000000000 118 | Size.Height = 2.000000000000000000 119 | Size.PlatformDefault = False 120 | Stroke.Kind = None 121 | Stroke.Thickness = 2.000000000000000000 122 | object FloatAnimation1: TFloatAnimation 123 | Enabled = True 124 | Duration = 2.000000000000000000 125 | Loop = True 126 | PropertyName = 'Position.Y' 127 | StartValue = 0.000000000000000000 128 | StopValue = 0.000000000000000000 129 | end 130 | end 131 | object rectLefTop: TRectangle 132 | Fill.Color = claWhite 133 | Size.Width = 8.000000000000000000 134 | Size.Height = 20.000000000000000000 135 | Size.PlatformDefault = False 136 | Stroke.Kind = None 137 | end 138 | object rectTopRight: TRectangle 139 | Anchors = [akTop, akRight] 140 | Fill.Color = claWhite 141 | Position.X = 141.000000000000000000 142 | Size.Width = 20.000000000000000000 143 | Size.Height = 8.000000000000000000 144 | Size.PlatformDefault = False 145 | Stroke.Kind = None 146 | end 147 | object rectLeftBottom: TRectangle 148 | Anchors = [akLeft, akBottom] 149 | Fill.Color = claWhite 150 | Position.Y = 282.000000000000000000 151 | Size.Width = 8.000000000000000000 152 | Size.Height = 20.000000000000000000 153 | Size.PlatformDefault = False 154 | Stroke.Kind = None 155 | end 156 | object rectRightTop: TRectangle 157 | Anchors = [akTop, akRight] 158 | Fill.Color = claWhite 159 | Position.X = 153.000000000000000000 160 | Size.Width = 8.000000000000000000 161 | Size.Height = 20.000000000000000000 162 | Size.PlatformDefault = False 163 | Stroke.Kind = None 164 | end 165 | object rectTopLeft: TRectangle 166 | Fill.Color = claWhite 167 | Size.Width = 20.000000000000000000 168 | Size.Height = 8.000000000000000000 169 | Size.PlatformDefault = False 170 | Stroke.Kind = None 171 | end 172 | object rectRightBottom: TRectangle 173 | Anchors = [akRight, akBottom] 174 | Fill.Color = claWhite 175 | Position.X = 153.000000000000000000 176 | Position.Y = 282.000000000000000000 177 | Size.Width = 8.000000000000000000 178 | Size.Height = 20.000000000000000000 179 | Size.PlatformDefault = False 180 | Stroke.Kind = None 181 | end 182 | object Rectangle5: TRectangle 183 | Anchors = [akLeft, akBottom] 184 | Fill.Color = claWhite 185 | Position.Y = 294.000000000000000000 186 | Size.Width = 20.000000000000000000 187 | Size.Height = 8.000000000000000000 188 | Size.PlatformDefault = False 189 | Stroke.Kind = None 190 | end 191 | object Rectangle6: TRectangle 192 | Anchors = [akRight, akBottom] 193 | Fill.Color = claWhite 194 | Position.X = 141.000000000000000000 195 | Position.Y = 294.000000000000000000 196 | Size.Width = 20.000000000000000000 197 | Size.Height = 8.000000000000000000 198 | Size.PlatformDefault = False 199 | Stroke.Kind = None 200 | end 201 | end 202 | end 203 | end 204 | object Layout1: TRectangle 205 | Align = Top 206 | Fill.Color = x80000000 207 | Size.Width = 401.000000000000000000 208 | Size.Height = 48.000000000000000000 209 | Size.PlatformDefault = False 210 | Stroke.Kind = None 211 | object btnBack: TSpeedButton 212 | Align = Left 213 | ModalResult = 2 214 | Margins.Left = 10.000000000000000000 215 | Position.X = 10.000000000000000000 216 | Size.Width = 48.000000000000000000 217 | Size.Height = 48.000000000000000000 218 | Size.PlatformDefault = False 219 | StyleLookup = 'backtoolbutton' 220 | Text = #36820#22238 221 | TouchTargetExpansion.Left = 10.000000000000000000 222 | end 223 | end 224 | object Rectangle1: TRectangle 225 | Align = Bottom 226 | Fill.Color = x80000000 227 | Position.Y = 514.000000000000000000 228 | Size.Width = 401.000000000000000000 229 | Size.Height = 48.000000000000000000 230 | Size.PlatformDefault = False 231 | Stroke.Kind = None 232 | object LabelFPS: TLabel 233 | Align = Client 234 | StyledSettings = [Family, Size, Style] 235 | Size.Width = 152.000000000000000000 236 | Size.Height = 48.000000000000000000 237 | Size.PlatformDefault = False 238 | TextSettings.FontColor = claWhite 239 | Text = 'LabelFPS' 240 | end 241 | object lblResult: TLabel 242 | Align = Right 243 | StyledSettings = [Family, Size, Style] 244 | Position.X = 152.000000000000000000 245 | Size.Width = 249.000000000000000000 246 | Size.Height = 48.000000000000000000 247 | Size.PlatformDefault = False 248 | TextSettings.FontColor = claWhite 249 | end 250 | end 251 | object MediaPlayer1: TMediaPlayer 252 | Left = 344 253 | Top = 264 254 | end 255 | object ActionList1: TActionList 256 | Left = 184 257 | Top = 264 258 | object TakePhotoFromLibraryAction1: TTakePhotoFromLibraryAction 259 | Category = 'Media Library' 260 | end 261 | end 262 | end 263 | -------------------------------------------------------------------------------- /ScanCodeDemo/SIMD/FastUtils.pas: -------------------------------------------------------------------------------- 1 | unit FastUtils; 2 | { NEON/Arm64 optimized assembly routines for RGBA<>BGRA conversion, YV12>RGBA 3 | conversion and bitmap rotation } 4 | 5 | interface 6 | 7 | {$IFDEF IOS} 8 | { Swaps the Red and Blue components of pixels in a memory buffer. 9 | 10 | Parameters: 11 | ASrc: points to the source buffer containing the pixels to convert. 12 | ADst: points to the destination buffer for the converted pixels. May be 13 | the same as ASrc. 14 | APixelCount: the number of pixels to convert. 15 | 16 | The Src and Dst buffers must have room for at least PixelCount * 4 bytes. } 17 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 18 | {$ENDIF} 19 | 20 | {$IFDEF ANDROID} 21 | { Converts a buffer from YV12 format to RGBA format. 22 | 23 | Parameters: 24 | AYPtr: pointer to the source Y (luminance) plane 25 | AUPtr: pointer to the source U (chrominance) plane 26 | AVPtr: pointer to the source V (chrominance) plane 27 | ARGBAPtr: pointer to the target interleaved RGBA buffer 28 | AYStride: number of bytes between two rows in the Y plane 29 | AUVStride: number of bytes between two rows in the U and V planes 30 | ARGBAStride: number of bytes between two rows in the RGBA buffer 31 | AWidth: width of the image to convert (must be even). 32 | AHeight: height of the image to convert (must be even). 33 | 34 | The buffers must be large enough to accomodate AWidth * AHeight pixels in 35 | their corresponding format. 36 | 37 | The alpha values will be set to $FF (opaque) 38 | 39 | NOTE: Currently, this procedure only works when AWidth is a multiple of 16 and 40 | AHeight is a multiple of 2. If this is not the case, then some rightmost and 41 | bottommost pixels will not get converted. } 42 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 43 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 44 | 45 | { Rotates a 32-bit bitmap 0, 90, 180 or 270 degrees. 46 | 47 | Parameters: 48 | ASrc: pointer to the source bitmap data 49 | ADst: pointer to the target bitmap data. This must be different than ASrc. 50 | The ASrc and ADst buffers may not share any data. 51 | ASrcWidth: width of the source bitmap (must be a multiple of 4) 52 | ASrcHeight: height of the source bitmap (must be a multiple of 4) 53 | AAngle: the angle of rotation (0, 90, 180 or 270) 54 | 55 | When rotating 0 or 180 degrees, the dimensions of ADst must match the 56 | dimensions of ASrc. When rotating 90 or 270 degrees, the width of ASrc must 57 | match the height of ADst and the height of ASrc must match the width of ADst. 58 | 59 | Furthermore, this routine expects the dimensions to be a multiple of 4. If 60 | not, an assertion will be raised and the results may be unpredictable. } 61 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 62 | ASrcHeight: Integer; const AAngle: Integer); 63 | {$ENDIF} 64 | 65 | implementation 66 | 67 | uses 68 | System.UITypes; 69 | 70 | const 71 | {$IF Defined(IOS)} 72 | LIB_FAST_UTILS = 'libfastutils.a'; 73 | _PU = ''; 74 | {$ELSEIF Defined(ANDROID)} 75 | LIB_FAST_UTILS = 'libfastutils-android.a'; 76 | _PU = '_'; 77 | {$ENDIF} 78 | 79 | {$IFDEF IOS} 80 | procedure swap_rb(ASrc, ADst: Pointer; ACount: Integer); cdecl; 81 | external LIB_FAST_UTILS name _PU + 'swap_rb'; 82 | 83 | procedure SwapRB(const ASrc, ADst: Pointer; const APixelCount: Integer); 84 | var 85 | NeonCount, Remainder: Integer; 86 | S, D: PAlphaColorRec; 87 | Temp: Byte; 88 | begin 89 | NeonCount := APixelCount shr 4; 90 | Remainder := APixelCount and 15; 91 | 92 | if (NeonCount > 0) then 93 | swap_rb(ASrc, ADst, NeonCount); 94 | 95 | if (Remainder > 0) then 96 | begin 97 | S := ASrc; 98 | D := ADst; 99 | Inc(S, NeonCount * 16); 100 | Inc(D, NeonCount * 16); 101 | if (ASrc = ADst) then 102 | begin 103 | while (Remainder > 0) do 104 | begin 105 | Temp := D.B; 106 | D.B := D.R; 107 | D.R := Temp; 108 | Inc(D); 109 | Dec(Remainder); 110 | end; 111 | end 112 | else 113 | begin 114 | while (Remainder > 0) do 115 | begin 116 | D.B := S.R; 117 | D.G := S.G; 118 | D.R := S.B; 119 | D.A := S.A; 120 | Inc(S); 121 | Inc(D); 122 | Dec(Remainder); 123 | end; 124 | end; 125 | end; 126 | end; 127 | {$ENDIF} 128 | 129 | {$IFDEF ANDROID} 130 | procedure yv12_to_rgba(AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 131 | AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); cdecl; 132 | external LIB_FAST_UTILS name _PU + 'yv12_to_rgba'; 133 | 134 | procedure YV12ToRGBA(const AYPtr, AUPtr, AVPtr, ARGBAPtr: Pointer; 135 | const AYStride, AUVStride, ARGBAStride, AWidth, AHeight: Integer); 136 | begin 137 | yv12_to_rgba(AYPtr, AUPtr, AVPtr, ARGBAPtr, AYStride, AUVStride, 138 | ARGBAStride, AWidth and (not 15), AHeight and (not 1)); 139 | end; 140 | 141 | procedure RotateBitmap0Degrees(const ASrc, ADst: Pointer; const ASrcWidth, 142 | ASrcHeight: Integer); 143 | begin 144 | Move(ASrc^, ADst^, ASrcWidth * ASrcHeight * 4); 145 | end; 146 | 147 | procedure RotateBitmap90Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 148 | external LIB_FAST_UTILS name _PU + 'rotate_90'; 149 | 150 | procedure RotateBitmap180Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 151 | external LIB_FAST_UTILS name _PU + 'rotate_180'; 152 | 153 | procedure RotateBitmap270Degrees(ASrc, ADst: Pointer; ASrcWidth, ASrcHeight: Integer); cdecl; 154 | external LIB_FAST_UTILS name _PU + 'rotate_270'; 155 | 156 | procedure RotateBitmap(const ASrc, ADst: Pointer; const ASrcWidth, 157 | ASrcHeight: Integer; const AAngle: Integer); 158 | begin 159 | if (ASrcWidth <= 0) or (ASrcHeight <= 0) then 160 | Exit; 161 | 162 | Assert(Assigned(ASrc)); 163 | Assert(Assigned(ADst)); 164 | Assert((ASrcHeight and 3) = 0); 165 | Assert((ASrcWidth and 3) = 0); 166 | 167 | case AAngle of 168 | 0: RotateBitmap0Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 169 | 90: RotateBitmap90Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 170 | 180: RotateBitmap180Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 171 | 270: RotateBitmap270Degrees(ASrc, ADst, ASrcWidth, ASrcHeight); 172 | else 173 | Assert(False); 174 | end; 175 | end; 176 | {$ENDIF} 177 | 178 | end. 179 | -------------------------------------------------------------------------------- /ScanCodeDemo/SIMD/libfastutils-android.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/ScanCodeDemo/SIMD/libfastutils-android.a -------------------------------------------------------------------------------- /ScanCodeDemo/SIMD/libfastutils.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/ScanCodeDemo/SIMD/libfastutils.a -------------------------------------------------------------------------------- /ScanCodeDemo/ScanCodeDemo.dpr: -------------------------------------------------------------------------------- 1 | program ScanCodeDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | QMScanCode in 'QMScanCode.pas' {QMScanCodeForm}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TQMScanCodeForm, QMScanCodeForm); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /ScanCodeDemo/readme.md: -------------------------------------------------------------------------------- 1 | 本 demo优化了相机的聚焦和扫描,识别部分使用的还是zxing,需要下载ZXing.Delphi进行编译 2 | 3 | ZXing.Delphi项目地址: 4 | https://github.com/Spelt/ZXing.Delphi 5 |   6 | 支持Berlin版本,如果SIMD版本出现问题,选择Fast版本,其他问题可到QQ群咨询,群号:165232328 7 | -------------------------------------------------------------------------------- /ScanCodeDemo/res/raw/beep.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/ScanCodeDemo/res/raw/beep.ogg -------------------------------------------------------------------------------- /TestButton/Main.fmx: -------------------------------------------------------------------------------- 1 | object Form1: TForm1 2 | Left = 0 3 | Top = 0 4 | Caption = 'Button by Aone' 5 | ClientHeight = 480 6 | ClientWidth = 640 7 | StyleBook = StyleBook1 8 | FormFactor.Width = 320 9 | FormFactor.Height = 480 10 | FormFactor.Devices = [Desktop] 11 | DesignerMasterStyle = 0 12 | object Rectangle1: TRectangle 13 | Fill.Color = claBrown 14 | HitTest = False 15 | Position.X = 5.000000000000000000 16 | Position.Y = 5.000000000000000000 17 | Size.Width = 251.000000000000000000 18 | Size.Height = 145.000000000000000000 19 | Size.PlatformDefault = False 20 | Stroke.Kind = None 21 | XRadius = 20.000000000000000000 22 | YRadius = 20.000000000000000000 23 | object Rectangle2: TRectangle 24 | Align = Client 25 | Fill.Color = claRed 26 | Margins.Bottom = 5.000000000000000000 27 | Size.Width = 251.000000000000000000 28 | Size.Height = 140.000000000000000000 29 | Size.PlatformDefault = False 30 | Stroke.Kind = None 31 | XRadius = 20.000000000000000000 32 | YRadius = 20.000000000000000000 33 | OnMouseDown = Rectangle2MouseDown 34 | OnMouseUp = Rectangle2MouseUp 35 | OnMouseLeave = Rectangle2MouseLeave 36 | object Text1: TText 37 | Align = Client 38 | HitTest = False 39 | Size.Width = 251.000000000000000000 40 | Size.Height = 140.000000000000000000 41 | Size.PlatformDefault = False 42 | Text = 'test' 43 | TextSettings.Font.Size = 50.000000000000000000 44 | TextSettings.FontColor = claWhite 45 | end 46 | object FloatAnimation1: TFloatAnimation 47 | Duration = 0.200000002980232200 48 | PropertyName = 'Margins.Bottom' 49 | StartValue = 5.000000000000000000 50 | StopValue = 0.000000000000000000 51 | Trigger = 'IsMouseOver=true' 52 | TriggerInverse = 'IsMouseOver=false' 53 | end 54 | end 55 | object ShadowEffect1: TShadowEffect 56 | Distance = 3.000000000000000000 57 | Direction = 45.000000000000000000 58 | Softness = 0.300000011920929000 59 | Opacity = 0.600000023841857900 60 | ShadowColor = claBlack 61 | end 62 | end 63 | object btn1: TButton 64 | Position.X = 288.000000000000000000 65 | Position.Y = 8.000000000000000000 66 | Size.Width = 249.000000000000000000 67 | Size.Height = 145.000000000000000000 68 | Size.PlatformDefault = False 69 | StyleLookup = 'btn1Style1' 70 | TabOrder = 0 71 | Text = 'test' 72 | end 73 | object StyleBook1: TStyleBook 74 | Styles = < 75 | item 76 | end 77 | item 78 | Platform = 'Windows 10 Desktop' 79 | ResourcesBin = { 80 | 464D585F5354594C4520322E3501060A62746E315374796C6531032507060A62 81 | 746E325374796C6531031E07005450463007544C61796F757400095374796C65 82 | 4E616D65060A62746E315374796C65310A506F736974696F6E2E580500000000 83 | 0000009607400A506F736974696F6E2E5905000000000000009B07400A53697A 84 | 652E576964746805000000000000808807400B53697A652E4865696768740500 85 | 000000000000C205401453697A652E506C6174666F726D44656661756C740808 86 | 5461624F726465720200000A5452656374616E676C6500095374796C654E616D 87 | 65060A6261636B67726F756E6405416C69676E0708436F6E74656E74730A4669 88 | 6C6C2E436F6C6F720708636C6142726F776E0748697454657374080A53697A65 89 | 2E576964746805000000000000808807400B53697A652E486569676874050000 90 | 0000000000C205401453697A652E506C6174666F726D44656661756C74080B53 91 | 74726F6B652E4B696E6407044E6F6E6507585261646975730500000000000000 92 | A0034007595261646975730500000000000000A00340000A5452656374616E67 93 | 6C6507546F7052656374095374796C654E616D65060F72656374616E676C6531 94 | 7374796C6505416C69676E0708436F6E74656E74730A46696C6C2E436F6C6F72 95 | 0706636C615265640748697454657374080E4D617267696E732E426F74746F6D 96 | 0500000000000000A001400A53697A652E576964746805000000000000808807 97 | 400B53697A652E4865696768740500000000000000B805401453697A652E506C 98 | 6174666F726D44656661756C74080B5374726F6B652E4B696E6407044E6F6E65 99 | 07585261646975730500000000000000A0034007595261646975730500000000 100 | 000000A00340000F54466C6F6174416E696D6174696F6E00095374796C654E61 101 | 6D650614666C6F6174616E696D6174696F6E317374796C65084475726174696F 102 | 6E050000000000CDCCCCFA3F0C50726F70657274794E616D650616546F705265 103 | 63742E4D617267696E732E426F74746F6D0A537461727456616C756505000000 104 | 00000000A001400953746F7056616C7565050000000000000000000007547269 105 | 67676572060E4973507265737365643D747275650E54726967676572496E7665 106 | 727365060F4973507265737365643D66616C7365000000000654476C79706800 107 | 095374796C654E616D65060A676C7970687374796C650C4D617267696E732E4C 108 | 6566740500000000000000C000400B4D617267696E732E546F70050000000000 109 | 00008000400D4D617267696E732E5269676874050000000000000080FF3F0E4D 110 | 617267696E732E426F74746F6D050000000000000080004005416C69676E0704 111 | 4C6566740A53697A652E576964746805000000000000008003400B53697A652E 112 | 48656967687405000000000000008003401453697A652E506C6174666F726D44 113 | 656661756C740800001654427574746F6E5374796C65546578744F626A656374 114 | 00095374796C654E616D6506047465787405416C69676E0706436C69656E7406 115 | 4C6F636B6564090C4D617267696E732E4C656674050000000000000080FF3F0B 116 | 4D617267696E732E546F7005000000000000008000400D4D617267696E732E52 117 | 69676874050000000000000080FF3F0E4D617267696E732E426F74746F6D0500 118 | 0000000000008000400A53697A652E576964746805000000000000808707400B 119 | 53697A652E4865696768740500000000000000BA05401453697A652E506C6174 120 | 666F726D44656661756C7408165465787453657474696E67732E466F6E742E53 121 | 697A650500000000000000C80440165465787453657474696E67732E466F6E74 122 | 436F6C6F720708636C6157686974650C536861646F772E436F6C6F7207097834 123 | 3030303030303010536861646F772E4F66667365742E594902FD0D536861646F 124 | 7756697369626C650908486F74436F6C6F720708636C6157686974650F486F74 125 | 536861646F772E436F6C6F72070978343030303030303013486F74536861646F 126 | 772E4F66667365742E594902FD0C466F6375736564436F6C6F720708636C6157 127 | 6869746513466F6375736564536861646F772E436F6C6F720709783430303030 128 | 30303017466F6375736564536861646F772E4F66667365742E594902FD0B4E6F 129 | 726D616C436F6C6F720708636C615768697465124E6F726D616C536861646F77 130 | 2E436F6C6F720709783430303030303030164E6F726D616C536861646F772E4F 131 | 66667365742E594902FD0C50726573736564436F6C6F720708636C6157686974 132 | 651350726573736564536861646F772E436F6C6F720709783430303030303030 133 | 1750726573736564536861646F772E4F66667365742E594902FD00000D545368 134 | 61646F7745666665637400095374796C654E616D650612736861646F77656666 135 | 656374317374796C650844697374616E63650500000000000000C00040094469 136 | 72656374696F6E0500000000000000B4044008536F66746E6573730500000000 137 | 009A9999FD3F074F7061636974790500000000009A9999FE3F0B536861646F77 138 | 436F6C6F720708636C61426C61636B0000005450463007544C61796F75740009 139 | 5374796C654E616D65060A62746E325374796C65310A506F736974696F6E2E58 140 | 0500000000000000C607400A506F736974696F6E2E590500000000000000AE07 141 | 400A53697A652E57696474680500000000000000A005400B53697A652E486569 142 | 6768740500000000000000B003401453697A652E506C6174666F726D44656661 143 | 756C74080756697369626C6508085461624F726465720201001254427574746F 144 | 6E5374796C654F626A65637400095374796C654E616D65060A6261636B67726F 145 | 756E6405416C69676E0708436F6E74656E74730C536F757263654C6F6F6B7570 146 | 061B57696E646F7773203130204465736B746F707374796C652E706E670A5369 147 | 7A652E57696474680500000000000000A005400B53697A652E48656967687405 148 | 00000000000000B003401453697A652E506C6174666F726D44656661756C7408 149 | 07486F744C696E6B0E010E436170496E736574732E4C65667405000000000000 150 | 00C000400D436170496E736574732E546F700500000000000000C000400F4361 151 | 70496E736574732E52696768740500000000000000C0004010436170496E7365 152 | 74732E426F74746F6D0500000000000000C000400F536F75726365526563742E 153 | 4C65667405000000000000008001400E536F75726365526563742E546F700500 154 | 000000000000C7064010536F75726365526563742E5269676874050000000000 155 | 0000A8054011536F75726365526563742E426F74746F6D0500000000000000E4 156 | 064000000B466F63757365644C696E6B0E010E436170496E736574732E4C6566 157 | 740500000000000000C000400D436170496E736574732E546F70050000000000 158 | 0000C000400F436170496E736574732E52696768740500000000000000C00040 159 | 10436170496E736574732E426F74746F6D0500000000000000C000400F536F75 160 | 726365526563742E4C65667405000000000000008001400E536F757263655265 161 | 63742E546F70050000000000008082074010536F75726365526563742E526967 162 | 68740500000000000000A8054011536F75726365526563742E426F74746F6D05 163 | 0000000000000091074000000A4E6F726D616C4C696E6B0E010E436170496E73 164 | 6574732E4C6566740500000000000000C000400D436170496E736574732E546F 165 | 700500000000000000C000400F436170496E736574732E526967687405000000 166 | 00000000C0004010436170496E736574732E426F74746F6D0500000000000000 167 | C000400F536F75726365526563742E4C65667405000000000000008001400E53 168 | 6F75726365526563742E546F700500000000000000A8064010536F7572636552 169 | 6563742E52696768740500000000000000A8054011536F75726365526563742E 170 | 426F74746F6D0500000000000000C5064000000B507265737365644C696E6B0E 171 | 010E436170496E736574732E4C6566740500000000000000C000400D43617049 172 | 6E736574732E546F700500000000000000C000400F436170496E736574732E52 173 | 696768740500000000000000C0004010436170496E736574732E426F74746F6D 174 | 0500000000000000C000400F536F75726365526563742E4C6566740500000000 175 | 0000008001400E536F75726365526563742E546F700500000000000000E60640 176 | 10536F75726365526563742E52696768740500000000000000A8054011536F75 177 | 726365526563742E426F74746F6D0500000000000080810740000013546F7563 178 | 68416E696D6174696F6E2E4C696E6B0E0000000654476C79706800095374796C 179 | 654E616D65060A676C7970687374796C650C4D617267696E732E4C6566740500 180 | 000000000000C000400B4D617267696E732E546F700500000000000000800040 181 | 0D4D617267696E732E5269676874050000000000000080FF3F0E4D617267696E 182 | 732E426F74746F6D050000000000000080004005416C69676E07044C6566740A 183 | 53697A652E576964746805000000000000008003400B53697A652E4865696768 184 | 7405000000000000008003401453697A652E506C6174666F726D44656661756C 185 | 740800001654427574746F6E5374796C65546578744F626A6563740009537479 186 | 6C654E616D6506047465787405416C69676E0706436C69656E74064C6F636B65 187 | 64090C4D617267696E732E4C656674050000000000000080FF3F0B4D61726769 188 | 6E732E546F7005000000000000008000400D4D617267696E732E526967687405 189 | 0000000000000080FF3F0E4D617267696E732E426F74746F6D05000000000000 190 | 008000400A53697A652E576964746805000000000000009C05400B53697A652E 191 | 48656967687405000000000000009003401453697A652E506C6174666F726D44 192 | 656661756C74080D536861646F7756697369626C650808486F74436F6C6F7207 193 | 08636C61426C61636B0C466F6375736564436F6C6F720708636C61426C61636B 194 | 0B4E6F726D616C436F6C6F720708636C61426C61636B0C50726573736564436F 195 | 6C6F720708636C61426C61636B000000} 196 | end> 197 | end 198 | end 199 | -------------------------------------------------------------------------------- /TestButton/Main.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/TestButton/Main.pas -------------------------------------------------------------------------------- /TestButton/TestButton.dpr: -------------------------------------------------------------------------------- 1 | program TestButton; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | Main in 'Main.pas' {Form1}; 7 | 8 | {$R *.res} 9 | 10 | begin 11 | Application.Initialize; 12 | Application.CreateForm(TForm1, Form1); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Tools/ResConvert.bdsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ResConvert.dpr 14 | 15 | 16 | 7.0 17 | 18 | 19 | 8 20 | 0 21 | 1 22 | 1 23 | 0 24 | 0 25 | 1 26 | 1 27 | 1 28 | 0 29 | 0 30 | 1 31 | 0 32 | 1 33 | 1 34 | 1 35 | 0 36 | 0 37 | 0 38 | 0 39 | 0 40 | 1 41 | 0 42 | 1 43 | 1 44 | 1 45 | True 46 | True 47 | WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; 48 | 49 | False 50 | 51 | True 52 | True 53 | True 54 | True 55 | True 56 | True 57 | True 58 | True 59 | True 60 | True 61 | True 62 | True 63 | True 64 | True 65 | True 66 | True 67 | True 68 | True 69 | True 70 | True 71 | True 72 | True 73 | True 74 | True 75 | True 76 | True 77 | True 78 | True 79 | True 80 | True 81 | True 82 | True 83 | True 84 | True 85 | True 86 | True 87 | True 88 | True 89 | True 90 | True 91 | True 92 | True 93 | True 94 | True 95 | True 96 | True 97 | False 98 | False 99 | False 100 | True 101 | True 102 | True 103 | True 104 | True 105 | True 106 | True 107 | True 108 | True 109 | True 110 | True 111 | True 112 | True 113 | True 114 | True 115 | 116 | 117 | 118 | 0 119 | 0 120 | False 121 | 1 122 | False 123 | False 124 | False 125 | 16384 126 | 1048576 127 | 4194304 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | False 140 | 141 | 142 | 143 | 144 | 145 | False 146 | 147 | 148 | True 149 | False 150 | 151 | 152 | False 153 | 154 | 155 | False 156 | False 157 | 1 158 | 0 159 | 0 160 | 0 161 | False 162 | False 163 | False 164 | False 165 | False 166 | 2052 167 | 936 168 | 169 | 170 | 171 | 172 | 1.0.0.0 173 | 174 | 175 | 176 | 177 | 178 | 1.0.0.0 179 | 180 | 181 | 182 | 183 | 190 | 191 | -------------------------------------------------------------------------------- /Tools/ResConvert.cfg: -------------------------------------------------------------------------------- 1 | -$A8 2 | -$B- 3 | -$C+ 4 | -$D+ 5 | -$E- 6 | -$F- 7 | -$G+ 8 | -$H+ 9 | -$I+ 10 | -$J- 11 | -$K- 12 | -$L+ 13 | -$M- 14 | -$N+ 15 | -$O+ 16 | -$P+ 17 | -$Q- 18 | -$R- 19 | -$S- 20 | -$T- 21 | -$U- 22 | -$V+ 23 | -$W- 24 | -$X+ 25 | -$YD 26 | -$Z1 27 | -cg 28 | -AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; 29 | -H+ 30 | -W+ 31 | -M 32 | -$M16384,1048576 33 | -K$00400000 34 | -LE"C:\Users\Public\Documents\RAD Studio\5.0\Bpl" 35 | -LN"C:\Users\Public\Documents\RAD Studio\5.0\Dcp" 36 | -------------------------------------------------------------------------------- /Tools/ResConvert.dpr: -------------------------------------------------------------------------------- 1 | program ResConvert; 2 | 3 | uses 4 | Forms, 5 | ResConvertMain in 'ResConvertMain.pas' {Form5}; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.CreateForm(TForm5, Form5); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /Tools/ResConvertMain.dfm: -------------------------------------------------------------------------------- 1 | object Form5: TForm5 2 | Left = 0 3 | Top = 0 4 | Caption = #20998#36776#29575#36716#25442 5 | ClientHeight = 240 6 | ClientWidth = 483 7 | Color = clBtnFace 8 | Font.Charset = DEFAULT_CHARSET 9 | Font.Color = clWindowText 10 | Font.Height = -11 11 | Font.Name = 'Tahoma' 12 | Font.Style = [] 13 | OldCreateOrder = False 14 | PixelsPerInch = 96 15 | TextHeight = 13 16 | object lbl1: TLabel 17 | Left = 256 18 | Top = 136 19 | Width = 16 20 | Height = 13 21 | Caption = 'lbl1' 22 | end 23 | object lbl2: TLabel 24 | Left = 104 25 | Top = 21 26 | Width = 24 27 | Height = 13 28 | Caption = #23485#24230 29 | end 30 | object lbl3: TLabel 31 | Left = 32 32 | Top = 83 33 | Width = 60 34 | Height = 13 35 | Caption = #30446#26631#20998#36776#29575 36 | end 37 | object lbl4: TLabel 38 | Left = 32 39 | Top = 43 40 | Width = 60 41 | Height = 13 42 | Caption = #32654#24037#20998#36776#29575 43 | end 44 | object lbl5: TLabel 45 | Left = 256 46 | Top = 21 47 | Width = 24 48 | Height = 13 49 | Caption = #39640#24230 50 | end 51 | object lbl6: TLabel 52 | Left = 32 53 | Top = 131 54 | Width = 48 55 | Height = 13 56 | Caption = #35774#35745#22352#26631 57 | end 58 | object lbl7: TLabel 59 | Left = 256 60 | Top = 176 61 | Width = 16 62 | Height = 13 63 | Caption = 'lbl1' 64 | end 65 | object lbl8: TLabel 66 | Left = 32 67 | Top = 171 68 | Width = 48 69 | Height = 13 70 | Caption = #36716#25442#22352#26631 71 | end 72 | object edtDesignY: TEdit 73 | Left = 256 74 | Top = 128 75 | Width = 121 76 | Height = 21 77 | TabOrder = 5 78 | OnChange = edtDesignYChange 79 | end 80 | object edtDesignX: TEdit 81 | Left = 104 82 | Top = 128 83 | Width = 121 84 | Height = 21 85 | TabOrder = 4 86 | OnChange = edtDesignXChange 87 | end 88 | object edtScreenHeight: TEdit 89 | Left = 256 90 | Top = 80 91 | Width = 121 92 | Height = 21 93 | TabOrder = 3 94 | Text = '540' 95 | end 96 | object edtScreenWidth: TEdit 97 | Left = 104 98 | Top = 80 99 | Width = 121 100 | Height = 21 101 | TabOrder = 2 102 | Text = '320' 103 | end 104 | object edtDesignHeight: TEdit 105 | Left = 256 106 | Top = 40 107 | Width = 121 108 | Height = 21 109 | TabOrder = 1 110 | Text = '1319' 111 | end 112 | object edtDesignWidth: TEdit 113 | Left = 104 114 | Top = 40 115 | Width = 121 116 | Height = 21 117 | TabOrder = 0 118 | Text = '720' 119 | end 120 | object edtConvertedY: TEdit 121 | Left = 256 122 | Top = 168 123 | Width = 121 124 | Height = 21 125 | TabOrder = 7 126 | end 127 | object edtConvertedX: TEdit 128 | Left = 104 129 | Top = 168 130 | Width = 121 131 | Height = 21 132 | TabOrder = 6 133 | end 134 | end 135 | -------------------------------------------------------------------------------- /Tools/ResConvertMain.pas: -------------------------------------------------------------------------------- 1 | unit ResConvertMain; 2 | 3 | interface 4 | 5 | uses 6 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 7 | Dialogs, StdCtrls; 8 | 9 | type 10 | TForm5 = class(TForm) 11 | edtDesignY: TEdit; 12 | edtDesignX: TEdit; 13 | edtScreenHeight: TEdit; 14 | edtScreenWidth: TEdit; 15 | lbl1: TLabel; 16 | lbl2: TLabel; 17 | lbl3: TLabel; 18 | lbl4: TLabel; 19 | edtDesignHeight: TEdit; 20 | edtDesignWidth: TEdit; 21 | lbl5: TLabel; 22 | lbl6: TLabel; 23 | edtConvertedY: TEdit; 24 | edtConvertedX: TEdit; 25 | lbl7: TLabel; 26 | lbl8: TLabel; 27 | procedure edtDesignXChange(Sender: TObject); 28 | procedure edtDesignYChange(Sender: TObject); 29 | private 30 | { Private declarations } 31 | FDesignWidth, FDesignHeight, FScreenWidth, FScreenHeight: Integer; 32 | function GetParameters: Boolean; 33 | public 34 | { Public declarations } 35 | end; 36 | 37 | var 38 | Form5: TForm5; 39 | 40 | implementation 41 | 42 | {$R *.dfm} 43 | 44 | procedure TForm5.edtDesignXChange(Sender: TObject); 45 | var 46 | X: Integer; 47 | CX: Double; 48 | begin 49 | if GetParameters then 50 | begin 51 | try 52 | X := StrToInt(edtDesignX.Text); 53 | CX := X * FScreenWidth / FDesignWidth; 54 | edtConvertedX.Text := FloatToStr(CX); 55 | except 56 | 57 | end; 58 | end; 59 | end; 60 | 61 | procedure TForm5.edtDesignYChange(Sender: TObject); 62 | var 63 | Y: Integer; 64 | CY: Double; 65 | begin 66 | if GetParameters then 67 | begin 68 | try 69 | Y := StrToInt(edtDesignY.Text); 70 | CY := Y * FScreenHeight / FDesignHeight; 71 | edtConvertedY.Text := FloatToStr(CY); 72 | except 73 | 74 | end; 75 | end; 76 | end; 77 | 78 | function TForm5.GetParameters: Boolean; 79 | begin 80 | try 81 | FDesignWidth := StrToInt(edtDesignWidth.Text); 82 | FDesignHeight := StrToInt(edtDesignHeight.Text); 83 | FScreenWidth := StrToInt(edtScreenWidth.Text); 84 | FScreenHeight := StrToInt(edtScreenHeight.Text); 85 | Result := True; 86 | except 87 | Result := False; 88 | end; 89 | end; 90 | 91 | end. 92 | -------------------------------------------------------------------------------- /ZXingScanDemo/AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | <%uses-permission%> 12 | 13 | 21 | 22 | <%application-meta-data%> 23 | <%services%> 24 | 26 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | <%activity%> 39 | <%receivers%> 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ZXingScanDemo/CameraConfigurationUtils.pas: -------------------------------------------------------------------------------- 1 | unit CameraConfigurationUtils; 2 | 3 | interface 4 | 5 | uses 6 | System.Classes, 7 | System.SysUtils, 8 | Fmx.Forms, 9 | Fmx.Dialogs, 10 | Androidapi.JNI.Hardware, 11 | Androidapi.JNI.JavaTypes, 12 | Androidapi.Helpers; 13 | 14 | type 15 | TCameraConfigurationUtils = class sealed 16 | private 17 | class function findSettableValue(name: string; 18 | const supportedValues: JList; desiredValues: TArray): JString; 19 | public 20 | class procedure setVideoStabilization(parameters: JCamera_Parameters); static; 21 | class procedure setBarcodeSceneMode(parameters: JCamera_Parameters); static; 22 | end; 23 | implementation 24 | 25 | { TCameraConfigurationUtils } 26 | 27 | class function TCameraConfigurationUtils.findSettableValue(name: string; 28 | const supportedValues: JList; desiredValues: TArray): JString; 29 | var 30 | desiredValue: JString; 31 | s: string; 32 | I: Integer; 33 | begin 34 | if supportedValues <> nil then 35 | begin 36 | for desiredValue in desiredValues do 37 | begin 38 | if supportedValues.contains( desiredValue) then 39 | Exit(desiredValue); 40 | end; 41 | end; 42 | Result := nil; 43 | end; 44 | 45 | class procedure TCameraConfigurationUtils.setBarcodeSceneMode(parameters: JCamera_Parameters ) ; 46 | var 47 | sceneMode: JString; 48 | begin 49 | if SameText(JStringToString(parameters.getSceneMode), JStringToString(TJCamera_Parameters.JavaClass.SCENE_MODE_BARCODE)) then 50 | begin 51 | // Log.i(TAG, "Barcode scene mode already set"); 52 | Exit; 53 | end; 54 | sceneMode := findSettableValue('scene mode', 55 | parameters.getSupportedSceneModes(), 56 | [TJCamera_Parameters.JavaClass.SCENE_MODE_BARCODE]); 57 | if (sceneMode <> nil) then 58 | parameters.setSceneMode(sceneMode); 59 | end; 60 | 61 | class procedure TCameraConfigurationUtils.setVideoStabilization(parameters: JCamera_Parameters); 62 | begin 63 | if (parameters.isVideoStabilizationSupported()) then 64 | begin 65 | if (parameters.getVideoStabilization()) then 66 | begin 67 | // Log.i(TAG, "Video stabilization already enabled"); 68 | end else begin 69 | // Log.i(TAG, "Enabling video stabilization..."); 70 | parameters.setVideoStabilization(true); 71 | end; 72 | end else begin 73 | // Log.i(TAG, "This device does not support video stabilization"); 74 | end; 75 | end; 76 | 77 | 78 | end. 79 | -------------------------------------------------------------------------------- /ZXingScanDemo/ZXingScanDemo.dpr: -------------------------------------------------------------------------------- 1 | program ZXingScanDemo; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | main in 'main.pas' {MainForm}, 7 | CameraConfigurationUtils in 'CameraConfigurationUtils.pas'; 8 | 9 | {$R *.res} 10 | 11 | begin 12 | Application.Initialize; 13 | Application.CreateForm(TMainForm, MainForm); 14 | Application.Run; 15 | end. 16 | -------------------------------------------------------------------------------- /ZXingScanDemo/ZXingScanDemo.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaoyipeng/DelphiDemos/HEAD/ZXingScanDemo/ZXingScanDemo.res -------------------------------------------------------------------------------- /ZXingScanDemo/ZXingScanDemo.stat: -------------------------------------------------------------------------------- 1 | [Stats] 2 | EditorSecs=42 3 | DesignerSecs=113 4 | InspectorSecs=74 5 | CompileSecs=51590 6 | OtherSecs=152 7 | StartTime=2016/8/5 9:53:47 8 | RealKeys=0 9 | EffectiveKeys=0 10 | DebugSecs=1 11 | -------------------------------------------------------------------------------- /ZXingScanDemo/main.LgXhdpiPh.fmx: -------------------------------------------------------------------------------- 1 | inherited MainForm_LgXhdpiPh: TMainForm_LgXhdpiPh 2 | ClientHeight = 695 3 | ClientWidth = 450 4 | DesignerMasterStyle = 2 5 | inherited Layout2: TLayout 6 | Size.Width = 450.000000000000000000 7 | Size.Height = 695.000000000000000000 8 | inherited ToolBar1: TToolBar 9 | Size.Width = 450.000000000000000000 10 | Size.Height = 48.000000000000000000 11 | inherited btnMenu: TButton 12 | Size.Width = 48.000000000000000000 13 | Size.Height = 48.000000000000000000 14 | end 15 | inherited lblScanStatus: TLabel 16 | Position.X = 250.363616943359400000 17 | Size.Width = 194.636352539062500000 18 | Size.Height = 47.999996185302730000 19 | end 20 | inherited chkAutoFocus: TCheckBox 21 | Size.Height = 48.000000000000000000 22 | end 23 | inherited btnAvailableSettings: TSpeedButton 24 | Position.Y = 8.000000000000000000 25 | Size.Height = 48.000000000000000000 26 | end 27 | end 28 | inherited imgCamera: TImage 29 | Size.Width = 450.000000000000000000 30 | Size.Height = 391.000000000000000000 31 | inherited lytScanMask: TLayout 32 | Size.Width = 450.000000000000000000 33 | Size.Height = 391.000000000000000000 34 | inherited Rectangle1: TRectangle 35 | Size.Width = 450.000000000000000000 36 | Size.Height = 100.000000000000000000 37 | end 38 | inherited Rectangle2: TRectangle 39 | Position.Y = 100.000000000000000000 40 | Size.Height = 191.000000000000000000 41 | end 42 | inherited Rectangle3: TRectangle 43 | Position.X = 330.000000000000000000 44 | Position.Y = 100.000000000000000000 45 | Size.Height = 191.000000000000000000 46 | end 47 | inherited Rectangle4: TRectangle 48 | Position.Y = 291.000000000000000000 49 | Size.Width = 450.000000000000000000 50 | Size.Height = 100.000000000000000000 51 | inherited Text1: TText 52 | Size.Width = 450.000000000000000000 53 | end 54 | end 55 | inherited lytScanWindow: TLayout 56 | Size.Width = 210.000000000000000000 57 | Size.Height = 191.000000000000000000 58 | inherited Line1: TLine 59 | Size.Width = 210.000000000000000000 60 | end 61 | inherited rectTopRight: TRectangle 62 | Position.X = 190.000000000000000000 63 | end 64 | inherited rectLeftBottom: TRectangle 65 | Position.Y = 171.000000000000000000 66 | end 67 | inherited rectRightTop: TRectangle 68 | Position.X = 202.000000000000000000 69 | end 70 | inherited rectRightBottom: TRectangle 71 | Position.X = 202.000000000000000000 72 | Position.Y = 171.000000000000000000 73 | end 74 | inherited Rectangle5: TRectangle 75 | Position.Y = 183.000000000000000000 76 | end 77 | inherited Rectangle6: TRectangle 78 | Position.X = 190.000000000000000000 79 | Position.Y = 183.000000000000000000 80 | end 81 | end 82 | end 83 | end 84 | inherited Memo1: TMemo 85 | Position.Y = 439.000000000000000000 86 | Size.Width = 450.000000000000000000 87 | Viewport.Width = 442.000000000000000000 88 | Viewport.Height = 200.000000000000000000 89 | end 90 | inherited ToolBar3: TToolBar 91 | Position.Y = 647.000000000000000000 92 | Size.Width = 450.000000000000000000 93 | Size.Height = 48.000000000000000000 94 | inherited btnStopCamera: TButton 95 | Size.Width = 120.000000000000000000 96 | Size.Height = 48.000000000000000000 97 | end 98 | inherited btnStartCamera: TButton 99 | Position.X = 120.000000000000000000 100 | Size.Width = 120.000000000000000000 101 | Size.Height = 48.000000000000000000 102 | end 103 | inherited lblStatus: TLabel 104 | Size.Width = 210.000000000000000000 105 | Size.Height = 48.000000000000000000 106 | end 107 | end 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /ZXingScanDemo/main.NmXhdpiPh.fmx: -------------------------------------------------------------------------------- 1 | inherited MainForm_NmXhdpiPh: TMainForm_NmXhdpiPh 2 | ClientHeight = 615 3 | ClientWidth = 400 4 | DesignerMasterStyle = 2 5 | inherited Layout2: TLayout 6 | Size.Width = 400.000000000000000000 7 | Size.Height = 615.000000000000000000 8 | inherited ToolBar1: TToolBar 9 | Size.Width = 400.000000000000000000 10 | Size.Height = 48.000000000000000000 11 | inherited btnMenu: TButton 12 | Size.Width = 48.000000000000000000 13 | Size.Height = 48.000000000000000000 14 | end 15 | inherited lblScanStatus: TLabel 16 | Position.X = 200.363616943359400000 17 | Size.Width = 194.636352539062500000 18 | Size.Height = 47.999996185302730000 19 | end 20 | inherited chkAutoFocus: TCheckBox 21 | Size.Height = 48.000000000000000000 22 | end 23 | inherited btnAvailableSettings: TSpeedButton 24 | Position.Y = 8.000000000000000000 25 | Size.Height = 48.000000000000000000 26 | end 27 | end 28 | inherited imgCamera: TImage 29 | Size.Width = 400.000000000000000000 30 | Size.Height = 311.000000000000000000 31 | inherited lytScanMask: TLayout 32 | Size.Width = 400.000000000000000000 33 | Size.Height = 311.000000000000000000 34 | inherited Rectangle1: TRectangle 35 | Size.Width = 400.000000000000000000 36 | Size.Height = 60.000000000000000000 37 | end 38 | inherited Rectangle2: TRectangle 39 | Position.Y = 60.000000000000000000 40 | Size.Width = 100.000000000000000000 41 | Size.Height = 191.000000000000000000 42 | end 43 | inherited Rectangle3: TRectangle 44 | Position.X = 300.000000000000000000 45 | Position.Y = 60.000000000000000000 46 | Size.Width = 100.000000000000000000 47 | Size.Height = 191.000000000000000000 48 | end 49 | inherited Rectangle4: TRectangle 50 | Position.Y = 251.000000000000000000 51 | Size.Width = 400.000000000000000000 52 | Size.Height = 60.000000000000000000 53 | inherited Text1: TText 54 | Size.Width = 400.000000000000000000 55 | end 56 | end 57 | inherited lytScanWindow: TLayout 58 | Size.Width = 200.000000000000000000 59 | Size.Height = 191.000000000000000000 60 | inherited Line1: TLine 61 | Size.Width = 200.000000000000000000 62 | end 63 | inherited rectTopRight: TRectangle 64 | Position.X = 180.000000000000000000 65 | end 66 | inherited rectLeftBottom: TRectangle 67 | Position.Y = 171.000000000000000000 68 | end 69 | inherited rectRightTop: TRectangle 70 | Position.X = 192.000000000000000000 71 | end 72 | inherited rectRightBottom: TRectangle 73 | Position.X = 192.000000000000000000 74 | Position.Y = 171.000000000000000000 75 | end 76 | inherited Rectangle5: TRectangle 77 | Position.Y = 183.000000000000000000 78 | end 79 | inherited Rectangle6: TRectangle 80 | Position.X = 180.000000000000000000 81 | Position.Y = 183.000000000000000000 82 | end 83 | end 84 | end 85 | end 86 | inherited Memo1: TMemo 87 | Position.Y = 359.000000000000000000 88 | Size.Width = 400.000000000000000000 89 | Viewport.Width = 392.000000000000000000 90 | Viewport.Height = 200.000000000000000000 91 | end 92 | inherited ToolBar3: TToolBar 93 | Position.Y = 567.000000000000000000 94 | Size.Width = 400.000000000000000000 95 | Size.Height = 48.000000000000000000 96 | inherited btnStopCamera: TButton 97 | Size.Height = 48.000000000000000000 98 | end 99 | inherited btnStartCamera: TButton 100 | Size.Height = 48.000000000000000000 101 | end 102 | inherited lblStatus: TLabel 103 | Size.Width = 66.000000000000000000 104 | Size.Height = 48.000000000000000000 105 | end 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /ZXingScanDemo/main.fmx: -------------------------------------------------------------------------------- 1 | object MainForm: TMainForm 2 | Left = 0 3 | Top = 0 4 | Caption = 'Delphi Camera Scanner' 5 | ClientHeight = 829 6 | ClientWidth = 480 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnCreate = FormCreate 11 | OnDestroy = FormDestroy 12 | DesignerMasterStyle = 2 13 | object Layout2: TLayout 14 | Align = Client 15 | Size.Width = 480.000000000000000000 16 | Size.Height = 829.000000000000000000 17 | Size.PlatformDefault = False 18 | TabOrder = 6 19 | object ToolBar1: TToolBar 20 | Size.Width = 480.000000000000000000 21 | Size.Height = 44.000000000000000000 22 | Size.PlatformDefault = False 23 | TabOrder = 0 24 | object btnMenu: TButton 25 | Align = Left 26 | Padding.Bottom = 4.000000000000000000 27 | Size.Width = 44.000000000000000000 28 | Size.Height = 44.000000000000000000 29 | Size.PlatformDefault = False 30 | StyleLookup = 'detailstoolbutton' 31 | TabOrder = 0 32 | Text = 'btnMenu' 33 | Visible = False 34 | end 35 | object lblScanStatus: TLabel 36 | Align = FitRight 37 | StyledSettings = [Size, Style, FontColor] 38 | Margins.Right = 5.000000000000000000 39 | Position.X = 297.000000000000000000 40 | Size.Width = 178.000000000000000000 41 | Size.Height = 44.000000000000000000 42 | Size.PlatformDefault = False 43 | TextSettings.Font.Family = 'Default' 44 | TextSettings.HorzAlign = Trailing 45 | Text = 'ScanStatus' 46 | end 47 | object chkAutoFocus: TCheckBox 48 | Align = Left 49 | IsChecked = True 50 | Size.Width = 120.000000000000000000 51 | Size.Height = 44.000000000000000000 52 | Size.PlatformDefault = False 53 | TabOrder = 8 54 | Text = #33258#21160#32858#28966 55 | end 56 | object btnAvailableSettings: TSpeedButton 57 | Position.X = 136.000000000000000000 58 | Size.Width = 161.000000000000000000 59 | Size.Height = 44.000000000000000000 60 | Size.PlatformDefault = False 61 | Text = #35774#32622#21015#34920 62 | OnClick = btnAvailableSettingsClick 63 | end 64 | end 65 | object imgCamera: TImage 66 | MultiResBitmap = < 67 | item 68 | end> 69 | Align = Client 70 | Size.Width = 480.000000000000000000 71 | Size.Height = 533.000000000000000000 72 | Size.PlatformDefault = False 73 | WrapMode = Stretch 74 | object lytScanMask: TLayout 75 | Align = Client 76 | Size.Width = 480.000000000000000000 77 | Size.Height = 533.000000000000000000 78 | Size.PlatformDefault = False 79 | Visible = False 80 | TabOrder = 0 81 | object Rectangle1: TRectangle 82 | Align = Top 83 | Fill.Color = x80000000 84 | Size.Width = 480.000000000000000000 85 | Size.Height = 130.000000000000000000 86 | Size.PlatformDefault = False 87 | Stroke.Kind = None 88 | end 89 | object Rectangle2: TRectangle 90 | Align = Left 91 | Fill.Color = x80000000 92 | Position.Y = 130.000000000000000000 93 | Size.Width = 120.000000000000000000 94 | Size.Height = 273.000000000000000000 95 | Size.PlatformDefault = False 96 | Stroke.Kind = None 97 | end 98 | object Rectangle3: TRectangle 99 | Align = Right 100 | Fill.Color = x80000000 101 | Position.X = 360.000000000000000000 102 | Position.Y = 130.000000000000000000 103 | Size.Width = 120.000000000000000000 104 | Size.Height = 273.000000000000000000 105 | Size.PlatformDefault = False 106 | Stroke.Kind = None 107 | end 108 | object Rectangle4: TRectangle 109 | Align = Bottom 110 | Fill.Color = x80000000 111 | Position.Y = 403.000000000000000000 112 | Size.Width = 480.000000000000000000 113 | Size.Height = 130.000000000000000000 114 | Size.PlatformDefault = False 115 | Stroke.Kind = None 116 | object Text1: TText 117 | Align = Top 118 | Margins.Top = 10.000000000000000000 119 | Position.Y = 10.000000000000000000 120 | Size.Width = 480.000000000000000000 121 | Size.Height = 49.000000000000000000 122 | Size.PlatformDefault = False 123 | Text = #35831#23545#20934#26041#26694#36827#34892#25195#25551 124 | TextSettings.Font.Size = 14.000000000000000000 125 | TextSettings.FontColor = claWhite 126 | end 127 | end 128 | object lytScanWindow: TLayout 129 | Align = Client 130 | Size.Width = 240.000000000000000000 131 | Size.Height = 273.000000000000000000 132 | Size.PlatformDefault = False 133 | TabOrder = 4 134 | object Line1: TLine 135 | Align = Top 136 | LineType = Bottom 137 | Size.Width = 240.000000000000000000 138 | Size.Height = 50.000000000000000000 139 | Size.PlatformDefault = False 140 | Stroke.Color = claBlue 141 | Stroke.Thickness = 2.000000000000000000 142 | object FloatAnimation1: TFloatAnimation 143 | Enabled = True 144 | Duration = 2.000000000000000000 145 | Loop = True 146 | PropertyName = 'Height' 147 | StartValue = 0.000000000000000000 148 | StopValue = 0.000000000000000000 149 | end 150 | end 151 | object rectLefTop: TRectangle 152 | Fill.Color = claWhite 153 | Size.Width = 8.000000000000000000 154 | Size.Height = 20.000000000000000000 155 | Size.PlatformDefault = False 156 | Stroke.Kind = None 157 | end 158 | object rectTopRight: TRectangle 159 | Anchors = [akTop, akRight] 160 | Fill.Color = claWhite 161 | Position.X = 220.000000000000000000 162 | Size.Width = 20.000000000000000000 163 | Size.Height = 8.000000000000000000 164 | Size.PlatformDefault = False 165 | Stroke.Kind = None 166 | end 167 | object rectLeftBottom: TRectangle 168 | Anchors = [akLeft, akBottom] 169 | Fill.Color = claWhite 170 | Position.Y = 253.000000000000000000 171 | Size.Width = 8.000000000000000000 172 | Size.Height = 20.000000000000000000 173 | Size.PlatformDefault = False 174 | Stroke.Kind = None 175 | end 176 | object rectRightTop: TRectangle 177 | Anchors = [akTop, akRight] 178 | Fill.Color = claWhite 179 | Position.X = 232.000000000000000000 180 | Size.Width = 8.000000000000000000 181 | Size.Height = 20.000000000000000000 182 | Size.PlatformDefault = False 183 | Stroke.Kind = None 184 | end 185 | object rectTopLeft: TRectangle 186 | Fill.Color = claWhite 187 | Size.Width = 20.000000000000000000 188 | Size.Height = 8.000000000000000000 189 | Size.PlatformDefault = False 190 | Stroke.Kind = None 191 | end 192 | object rectRightBottom: TRectangle 193 | Anchors = [akRight, akBottom] 194 | Fill.Color = claWhite 195 | Position.X = 232.000000000000000000 196 | Position.Y = 253.000000000000000000 197 | Size.Width = 8.000000000000000000 198 | Size.Height = 20.000000000000000000 199 | Size.PlatformDefault = False 200 | Stroke.Kind = None 201 | end 202 | object Rectangle5: TRectangle 203 | Anchors = [akLeft, akBottom] 204 | Fill.Color = claWhite 205 | Position.Y = 265.000000000000000000 206 | Size.Width = 20.000000000000000000 207 | Size.Height = 8.000000000000000000 208 | Size.PlatformDefault = False 209 | Stroke.Kind = None 210 | end 211 | object Rectangle6: TRectangle 212 | Anchors = [akRight, akBottom] 213 | Fill.Color = claWhite 214 | Position.X = 220.000000000000000000 215 | Position.Y = 265.000000000000000000 216 | Size.Width = 20.000000000000000000 217 | Size.Height = 8.000000000000000000 218 | Size.PlatformDefault = False 219 | Stroke.Kind = None 220 | end 221 | end 222 | end 223 | end 224 | object Memo1: TMemo 225 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] 226 | DataDetectorTypes = [] 227 | Align = Bottom 228 | Position.Y = 577.000000000000000000 229 | Size.Width = 480.000000000000000000 230 | Size.Height = 208.000000000000000000 231 | Size.PlatformDefault = False 232 | TabOrder = 1 233 | Viewport.Width = 472.000000000000000000 234 | Viewport.Height = 200.000000000000000000 235 | end 236 | object ToolBar3: TToolBar 237 | Align = MostBottom 238 | Position.Y = 785.000000000000000000 239 | Size.Width = 480.000000000000000000 240 | Size.Height = 44.000000000000000000 241 | Size.PlatformDefault = False 242 | TabOrder = 2 243 | object btnStopCamera: TButton 244 | Align = Left 245 | Size.Width = 151.000000000000000000 246 | Size.Height = 44.000000000000000000 247 | Size.PlatformDefault = False 248 | TabOrder = 1 249 | Text = #20572#27490#25195#25551 250 | OnClick = btnStopCameraClick 251 | end 252 | object btnStartCamera: TButton 253 | Align = Left 254 | Position.X = 151.000000000000000000 255 | Size.Width = 183.000000000000000000 256 | Size.Height = 44.000000000000000000 257 | Size.PlatformDefault = False 258 | TabOrder = 2 259 | Text = #24320#22987#25195#25551 260 | OnClick = btnStartCameraClick 261 | end 262 | object lblStatus: TLabel 263 | Align = Client 264 | Size.Width = 146.000000000000000000 265 | Size.Height = 44.000000000000000000 266 | Size.PlatformDefault = False 267 | end 268 | end 269 | end 270 | object CameraComponent1: TCameraComponent 271 | OnSampleBufferReady = CameraComponent1SampleBufferReady 272 | Left = 552 273 | Top = 88 274 | end 275 | end 276 | -------------------------------------------------------------------------------- /ZXingScanDemo/main.iPhone55in.fmx: -------------------------------------------------------------------------------- 1 | inherited MainForm_iPhone55in: TMainForm_iPhone55in 2 | ClientHeight = 716 3 | ClientWidth = 414 4 | DesignerMasterStyle = 2 5 | inherited Layout2: TLayout 6 | Size.Width = 414.000000000000000000 7 | Size.Height = 716.000000000000000000 8 | inherited ToolBar1: TToolBar 9 | Size.Width = 414.000000000000000000 10 | inherited lblScanStatus: TLabel 11 | Position.X = 231.000000000000000000 12 | end 13 | inherited btnAvailableSettings: TSpeedButton 14 | Position.Y = 8.000000000000000000 15 | end 16 | end 17 | inherited imgCamera: TImage 18 | Size.Width = 414.000000000000000000 19 | Size.Height = 420.000000000000000000 20 | end 21 | inherited Memo1: TMemo 22 | Position.Y = 464.000000000000000000 23 | Size.Width = 414.000000000000000000 24 | Viewport.Width = 406.000000000000000000 25 | Viewport.Height = 200.000000000000000000 26 | end 27 | inherited ToolBar3: TToolBar 28 | Position.Y = 672.000000000000000000 29 | Size.Width = 414.000000000000000000 30 | inherited lblStatus: TLabel 31 | Size.Width = 80.000000000000000000 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /ZXingScanDemo/main.pas: -------------------------------------------------------------------------------- 1 | unit main; 2 | { 3 | * Copyright 2015 E Spelt for test project stuff 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | 17 | * Implemented by E. Spelt for Delphi 18 | } 19 | interface 20 | 21 | uses 22 | System.SysUtils, System.Types, System.UITypes, System.Classes, 23 | System.Variants, 24 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, 25 | FMX.StdCtrls, FMX.Media, FMX.Platform, FMX.MultiView, FMX.ListView.Types, 26 | FMX.ListView, FMX.Layouts, System.Actions, FMX.ActnList, FMX.TabControl, 27 | FMX.ListBox, Threading, BarcodeFormat, ReadResult, 28 | FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, ScanManager, FMX.Ani 29 | {$IFDEF ANDROID} 30 | ,Androidapi.JNIBridge 31 | ,System.Rtti 32 | ,Androidapi.JNI.Hardware 33 | ,FMX.Media.Android 34 | ,CameraConfigurationUtils 35 | {$ENDIF} 36 | ; 37 | 38 | type 39 | TMainForm = class(TForm) 40 | btnStartCamera: TButton; 41 | btnStopCamera: TButton; 42 | lblScanStatus: TLabel; 43 | imgCamera: TImage; 44 | ToolBar1: TToolBar; 45 | btnMenu: TButton; 46 | Layout2: TLayout; 47 | ToolBar3: TToolBar; 48 | CameraComponent1: TCameraComponent; 49 | Memo1: TMemo; 50 | lblStatus: TLabel; 51 | lytScanMask: TLayout; 52 | Rectangle1: TRectangle; 53 | Rectangle2: TRectangle; 54 | Rectangle3: TRectangle; 55 | Rectangle4: TRectangle; 56 | lytScanWindow: TLayout; 57 | Line1: TLine; 58 | FloatAnimation1: TFloatAnimation; 59 | rectLefTop: TRectangle; 60 | rectTopRight: TRectangle; 61 | rectLeftBottom: TRectangle; 62 | rectRightTop: TRectangle; 63 | rectTopLeft: TRectangle; 64 | rectRightBottom: TRectangle; 65 | Rectangle5: TRectangle; 66 | Rectangle6: TRectangle; 67 | Text1: TText; 68 | chkAutoFocus: TCheckBox; 69 | btnAvailableSettings: TSpeedButton; 70 | procedure btnStartCameraClick(Sender: TObject); 71 | procedure FormCreate(Sender: TObject); 72 | procedure btnStopCameraClick(Sender: TObject); 73 | 74 | procedure FormDestroy(Sender: TObject); 75 | procedure CameraComponent1SampleBufferReady(Sender: TObject; 76 | const ATime: TMediaTime); 77 | procedure btnAvailableSettingsClick(Sender: TObject); 78 | private 79 | { Private declarations } 80 | FStartTime: TDateTime; 81 | FScanManager: TScanManager; 82 | FScanInProgress: Boolean; 83 | frameTake: Integer; 84 | procedure GetImage(); 85 | procedure FocusReady; 86 | function AppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; 87 | 88 | public 89 | { Public declarations } 90 | end; 91 | 92 | var 93 | MainForm: TMainForm; 94 | 95 | implementation 96 | 97 | {$R *.fmx} 98 | {$R *.NmXhdpiPh.fmx ANDROID} 99 | {$R *.LgXhdpiPh.fmx ANDROID} 100 | {$R *.iPhone55in.fmx IOS} 101 | 102 | type 103 | TMyCamera = class(TCameraComponent) 104 | 105 | end; 106 | 107 | {$IFDEF ANDROID} 108 | TAndroidCameraCallback = class(TJavaLocal, JCamera_AutoFocusCallback) 109 | private 110 | [Weak] FMainForm: TMainForm; 111 | public 112 | procedure onAutoFocus(success: Boolean; camera: JCamera); cdecl; 113 | end; 114 | 115 | procedure TAndroidCameraCallback.onAutoFocus(success: Boolean; camera: JCamera); cdecl; 116 | begin 117 | FMainForm.FocusReady; 118 | end; 119 | 120 | var 121 | CameraCallBack: TAndroidCameraCallback = nil; 122 | 123 | function GetCameraCallBack: TAndroidCameraCallback; 124 | begin 125 | if CameraCallBack = nil then 126 | CameraCallBack := TAndroidCameraCallback.Create; 127 | 128 | Result := TAndroidCameraCallback.Create; 129 | end; 130 | {$ENDIF} 131 | 132 | procedure TMainForm.FocusReady; 133 | begin 134 | 135 | end; 136 | 137 | procedure TMainForm.FormCreate(Sender: TObject); 138 | var 139 | AppEventSvc: IFMXApplicationEventService; 140 | begin 141 | 142 | lblScanStatus.Text := ''; 143 | frameTake := 0; 144 | 145 | { by default, we start with Front Camera and Flash Off } 146 | { cbFrontCamera.IsChecked := True; 147 | CameraComponent1.Kind := FMX.Media.TCameraKind.ckFrontCamera; 148 | 149 | cbFlashOff.IsChecked := True; 150 | if CameraComponent1.HasFlash then 151 | CameraComponent1.FlashMode := FMX.Media.TFlashMode.fmFlashOff; 152 | } 153 | 154 | { Add platform service to see camera state. } 155 | if TPlatformServices.Current.SupportsPlatformService 156 | (IFMXApplicationEventService, IInterface(AppEventSvc)) then 157 | AppEventSvc.SetApplicationEventHandler(AppEvent); 158 | 159 | CameraComponent1.Quality := FMX.Media.TVideoCaptureQuality.MediumQuality; 160 | lblScanStatus.Text := ''; 161 | FScanManager := TScanManager.Create(TBarcodeFormat.Auto, nil); 162 | end; 163 | 164 | procedure TMainForm.FormDestroy(Sender: TObject); 165 | begin 166 | FScanManager.Free; 167 | end; 168 | 169 | procedure TMainForm.btnAvailableSettingsClick(Sender: TObject); 170 | var 171 | Settings: TArray; 172 | I: Integer; 173 | s: string; 174 | begin 175 | // 176 | Settings := CameraComponent1.AvailableCaptureSettings; 177 | for I := 0 to High(Settings) do 178 | begin 179 | s := Format('%d: Width=%d, Height=%d, FrameRate=%f, Min=%f, Max=%f', 180 | [I+1, Settings[I].Width, Settings[I].Height, 181 | Settings[I].FrameRate, Settings[I].MinFrameRate, Settings[I].MaxFrameRate]); 182 | Memo1.Lines.Add(s); 183 | end; 184 | end; 185 | 186 | procedure TMainForm.btnStartCameraClick(Sender: TObject); 187 | var 188 | Setting: TVideoCaptureSetting; 189 | {$IFDEF ANDROID} 190 | JC: JCamera; 191 | Device: TCaptureDevice; 192 | ClassRef: TClass; 193 | ctx: TRttiContext; 194 | t: TRttiType; 195 | Params: JCamera_Parameters; 196 | {$ENDIF} 197 | begin 198 | FStartTime := Now; 199 | frameTake := 0; 200 | CameraComponent1.Active := False; 201 | 202 | Setting:= CameraComponent1.CaptureSetting; 203 | Setting.Width := 352; 204 | Setting.Height := 288; 205 | Setting.FrameRate := 30; 206 | Setting.SetFrameRate(30, 30); 207 | if chkAutoFocus.IsChecked then 208 | CameraComponent1.FocusMode := TFocusMode.ContinuousAutoFocus 209 | else 210 | CameraComponent1.FocusMode := TFocusMode.AutoFocus; 211 | CameraComponent1.SetCaptureSetting(Setting); 212 | CameraComponent1.Quality := TVideoCaptureQuality.MediumQuality; 213 | CameraComponent1.Kind := FMX.Media.TCameraKind.BackCamera; 214 | 215 | {$IFDEF ANDROID} 216 | Device := TMyCamera(CameraComponent1).Device; 217 | 218 | ClassRef := Device.ClassType; 219 | ctx := TRttiContext.Create; 220 | try 221 | t := ctx.GetType(ClassRef); 222 | JC := t.GetProperty('Camera').GetValue(Device).AsInterface as JCamera; 223 | TCameraConfigurationUtils.setBarcodeSceneMode(JC.getParameters); 224 | TCameraConfigurationUtils.setVideoStabilization(JC.getParameters); 225 | //JC.cancelAutoFocus(); 226 | //GetCameraCallback().FMainForm := Self; 227 | //JC.autoFocus(GetCameraCallback()); 228 | finally 229 | ctx.Free; 230 | end; 231 | {$ENDIF} 232 | CameraComponent1.Active := True; 233 | 234 | lblScanStatus.Text := ''; 235 | memo1.Lines.Clear; 236 | 237 | lytScanMask.Visible := True; 238 | FloatAnimation1.StopValue := lytScanWindow.Height; 239 | FloatAnimation1.Start; 240 | end; 241 | 242 | procedure TMainForm.btnStopCameraClick(Sender: TObject); 243 | begin 244 | CameraComponent1.Active := False; 245 | //self.imgCamera.Bitmap.Clear(0); 246 | FloatAnimation1.Stop; 247 | lytScanMask.Visible := False; 248 | end; 249 | 250 | procedure TMainForm.CameraComponent1SampleBufferReady(Sender: TObject; 251 | const ATime: TMediaTime); 252 | begin 253 | TThread.Synchronize(TThread.CurrentThread, GetImage); 254 | end; 255 | 256 | procedure TMainForm.GetImage; 257 | var 258 | scanBitmap: TBitmap; 259 | ReadResult: TReadResult; 260 | dt: TDateTime; 261 | fps: double; 262 | w, h, x, y: Integer; 263 | begin 264 | 265 | CameraComponent1.SampleBufferToBitmap(imgCamera.Bitmap, True); 266 | if (FScanInProgress) then 267 | begin 268 | Exit; 269 | end; 270 | 271 | inc(frameTake); 272 | // if (frameTake mod 4 <> 0) then 273 | // begin 274 | // Exit; 275 | // end; 276 | dt := (Now - FStartTime) * SecsPerDay; 277 | fps := (frameTake / dt); 278 | lblStatus.Text := Format('Frame:%d, FPS:%.2f', [frameTake, fps]); 279 | w := imgCamera.Bitmap.Width; 280 | h := imgCamera.Bitmap.Height; 281 | x := Round(w * lytScanWindow.Position.X / imgCamera.Width); 282 | y := Round(h * lytScanWindow.Position.Y / imgCamera.Height); 283 | 284 | scanBitmap := TBitmap.Create(); 285 | scanBitmap.SetSize(w - 2 * x, h - 2 * y); 286 | scanBitmap.Canvas.DrawBitmap(imgCamera.Bitmap, 287 | RectF(x, y, w - x, h - y), 288 | RectF(0,0,scanBitmap.Width, scanBitmap.Height), 289 | 1); 290 | // scanBitmap.Assign(imgCamera.Bitmap); 291 | 292 | TTask.Run( 293 | procedure 294 | begin 295 | 296 | try 297 | FScanInProgress := True; 298 | 299 | scanBitmap.Assign(imgCamera.Bitmap); 300 | 301 | ReadResult := FScanManager.Scan(scanBitmap); 302 | FScanInProgress := False; 303 | except 304 | on E: Exception do 305 | begin 306 | FScanInProgress := False; 307 | TThread.Synchronize(nil, 308 | procedure 309 | begin 310 | // lblScanStatus.Text := E.Message; 311 | // lblScanResults.Text := ''; 312 | end); 313 | 314 | if (scanBitmap <> nil) then 315 | begin 316 | scanBitmap.Free; 317 | end; 318 | 319 | Exit; 320 | 321 | end; 322 | 323 | end; 324 | 325 | TThread.Synchronize(nil, 326 | procedure 327 | begin 328 | 329 | if (length(lblScanStatus.Text) > 10) then 330 | begin 331 | lblScanStatus.Text := '*'; 332 | end; 333 | 334 | lblScanStatus.Text := lblScanStatus.Text + '*'; 335 | 336 | if (ReadResult <> nil) then 337 | begin 338 | memo1.Lines.Insert(0,ReadResult.Text); 339 | if Memo1.Lines.Count >= 10 then 340 | Memo1.Lines.Clear; 341 | end; 342 | 343 | if (scanBitmap <> nil) then 344 | begin 345 | scanBitmap.Free; 346 | end; 347 | 348 | FreeAndNil(ReadResult); 349 | 350 | end); 351 | end); 352 | 353 | end; 354 | 355 | { Make sure the ca mera is released if you're going away. } 356 | function TMainForm.AppEvent(AAppEvent: TApplicationEvent; 357 | AContext: TObject): Boolean; 358 | begin 359 | 360 | case AAppEvent of 361 | TApplicationEvent.WillBecomeInactive: 362 | CameraComponent1.Active := False; 363 | TApplicationEvent.EnteredBackground: 364 | CameraComponent1.Active := False; 365 | TApplicationEvent.WillTerminate: 366 | CameraComponent1.Active := False; 367 | end; 368 | 369 | end; 370 | 371 | initialization 372 | finalization 373 | //CameraCallBack.Free; 374 | end. 375 | --------------------------------------------------------------------------------