Ver Fonte

Merge Experimental FMX Support to Master Repository. (#1)

* added FMX Support.

* update README.

* update README

* replace AnsiString and AnsiChar with Char.
Ugochukwu Mmaduekwe há 7 anos atrás
pai
commit
e77797270c

+ 31 - 0
QRCodeGenLib.Demo/Delphi.Demo/QrCodeGeneratorDemoFMX.dpr

@@ -0,0 +1,31 @@
+program QrCodeGeneratorDemoFMX;
+
+uses
+  System.StartUpCopy,
+  FMX.Forms,
+  QlpArrayUtils in '..\..\QRCodeGenLib\src\Utils\QlpArrayUtils.pas',
+  QlpQRCodeGenLibTypes in '..\..\QRCodeGenLib\src\Utils\QlpQRCodeGenLibTypes.pas',
+  QlpBits in '..\..\QRCodeGenLib\src\Utils\QlpBits.pas',
+  QlpBitBuffer in '..\..\QRCodeGenLib\src\QRCodeGen\QlpBitBuffer.pas',
+  QlpQrSegment in '..\..\QRCodeGenLib\src\QRCodeGen\QlpQrSegment.pas',
+  QlpIQrSegment in '..\..\QRCodeGenLib\src\Interfaces\QlpIQrSegment.pas',
+  QlpQrSegmentMode in '..\..\QRCodeGenLib\src\QRCodeGen\QlpQrSegmentMode.pas',
+  QlpGuard in '..\..\QRCodeGenLib\src\Utils\QlpGuard.pas',
+  QlpReedSolomonGenerator in '..\..\QRCodeGenLib\src\QRCodeGen\QlpReedSolomonGenerator.pas',
+  QlpIReedSolomonGenerator in '..\..\QRCodeGenLib\src\Interfaces\QlpIReedSolomonGenerator.pas',
+  QlpQrTemplate in '..\..\QRCodeGenLib\src\QRCodeGen\QlpQrTemplate.pas',
+  QlpIQrTemplate in '..\..\QRCodeGenLib\src\Interfaces\QlpIQrTemplate.pas',
+  QlpQrCode in '..\..\QRCodeGenLib\src\QRCodeGen\QlpQrCode.pas',
+  QlpIQrCode in '..\..\QRCodeGenLib\src\Interfaces\QlpIQrCode.pas',
+  QlpQrCodeCommons in '..\..\QRCodeGenLib\src\QRCodeGen\QlpQrCodeCommons.pas',
+  QlpConverters in '..\..\QRCodeGenLib\src\Utils\QlpConverters.pas',
+  QrCodeGeneratorDemoFMXForm in 'QrCodeGeneratorDemoFMXForm.pas',
+  uQrCodeGeneratorDemoFMX in '..\src\uQrCodeGeneratorDemoFMX.pas';
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.CreateForm(TQRCodeGeneratorFMXDemoForm, QRCodeGeneratorFMXDemoForm);
+  Application.Run;
+end.

+ 37 - 0
QRCodeGenLib.Demo/Delphi.Demo/QrCodeGeneratorDemoFMXForm.fmx

@@ -0,0 +1,37 @@
+object QRCodeGeneratorFMXDemoForm: TQRCodeGeneratorFMXDemoForm
+  Left = 0
+  Top = 0
+  BorderIcons = [biSystemMenu, biMinimize]
+  BorderStyle = Single
+  Caption = 'QRCodeGeneratorFMXDemo'
+  ClientHeight = 383
+  ClientWidth = 640
+  Position = DesktopCenter
+  FormFactor.Width = 320
+  FormFactor.Height = 480
+  FormFactor.Devices = [Desktop]
+  DesignerMasterStyle = 0
+  object mmoLogger: TMemo
+    Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
+    DataDetectorTypes = []
+    ReadOnly = True
+    Position.X = 32.000000000000000000
+    Position.Y = 32.000000000000000000
+    Size.Width = 569.000000000000000000
+    Size.Height = 289.000000000000000000
+    Size.PlatformDefault = False
+    TabOrder = 0
+    Viewport.Width = 565.000000000000000000
+    Viewport.Height = 285.000000000000000000
+  end
+  object btnRunDemos: TButton
+    Position.X = 520.000000000000000000
+    Position.Y = 336.000000000000000000
+    Size.Width = 81.000000000000000000
+    Size.Height = 33.000000000000000000
+    Size.PlatformDefault = False
+    TabOrder = 1
+    Text = 'RunDemos'
+    OnClick = btnRunDemosClick
+  end
+end

+ 35 - 0
QRCodeGenLib.Demo/Delphi.Demo/QrCodeGeneratorDemoFMXForm.pas

@@ -0,0 +1,35 @@
+unit QrCodeGeneratorDemoFMXForm;
+
+interface
+
+uses
+  System.SysUtils, System.Types, System.UITypes, System.Classes,
+  System.Variants,
+  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
+  FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls,
+  uQrCodeGeneratorDemoFMX;
+
+type
+  TQRCodeGeneratorFMXDemoForm = class(TForm)
+    mmoLogger: TMemo;
+    btnRunDemos: TButton;
+    procedure btnRunDemosClick(Sender: TObject);
+  private
+    { Private declarations }
+  public
+    { Public declarations }
+  end;
+
+var
+  QRCodeGeneratorFMXDemoForm: TQRCodeGeneratorFMXDemoForm;
+
+implementation
+
+{$R *.fmx}
+
+procedure TQRCodeGeneratorFMXDemoForm.btnRunDemosClick(Sender: TObject);
+begin
+  TQrCodeGeneratorDemoFMX.RunAllDemos;
+end;
+
+end.

+ 306 - 0
QRCodeGenLib.Demo/src/uQrCodeGeneratorDemoFMX.pas

@@ -0,0 +1,306 @@
+unit uQrCodeGeneratorDemoFMX;
+
+interface
+
+uses
+  SysUtils,
+  UITypes,
+  FMX.Dialogs,
+  FMX.Graphics,
+  QlpIQrCode,
+  QlpQrCode,
+  QlpIQrSegment,
+  QlpQrSegment,
+  QlpQrSegmentMode,
+  QlpBitBuffer,
+  QlpConverters,
+  QlpQRCodeGenLibTypes;
+
+type
+  TQrCodeGeneratorDemoFMX = class sealed(TObject)
+  strict private
+    class function HTMLColorToTAlphaColor(const AHTMLColorHex: String)
+      : TAlphaColor; inline;
+    class procedure WriteQrCodeToFile(const AQrCode: IQrCode;
+      AScale, ABorder: Int32; const AFileName: String);
+
+    // Creates a single QR Code, then writes it to supported image formats and an SVG file.
+    class procedure DoBasicDemo();
+    // Creates a single QR Code, changes the colors (background and foreground) then writes it to supported image formats and an SVG file.
+    class procedure DoBasicDemoAndChangeColor();
+    // Creates a variety of QR Codes that exercise different features of the library, then writes each one to supported image formats and an SVG file.
+    class procedure DoVarietyDemo();
+    // Creates QR Codes with manually specified segments for better compactness, then writes each one to supported image formats and an SVG file.
+    class procedure DoSegmentDemo();
+    // Creates QR Codes with the same size and contents but different mask patterns, then writes each one to supported image formats and an SVG file.
+    class procedure DoMaskDemo();
+
+  public
+    class procedure RunAllDemos();
+  end;
+
+implementation
+
+uses
+  QrCodeGeneratorDemoFMXForm;
+
+{ TQrCodeGeneratorDemo }
+
+class function TQrCodeGeneratorDemoFMX.HTMLColorToTAlphaColor
+  (const AHTMLColorHex: String): TAlphaColor;
+var
+  Lr, Lg, Lb: Byte;
+  rec: TAlphaColorRec;
+begin
+{$IFDEF DEBUG}
+  System.Assert(System.Length(AHTMLColorHex) = 6);
+{$ENDIF DEBUG}
+  Lr := StrToInt('$' + System.Copy(AHTMLColorHex, 1, 2));
+  Lg := StrToInt('$' + System.Copy(AHTMLColorHex, 3, 2));
+  Lb := StrToInt('$' + System.Copy(AHTMLColorHex, 5, 2));
+  rec.A := $FF; // for transparency
+  rec.R := Lr;
+  rec.G := Lg;
+  rec.B := Lb;
+  Result := rec.Color;
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.DoBasicDemo;
+var
+  LText: String;
+  LErrCorLvl: TQrCode.TEcc;
+  LQrCode: IQrCode;
+  LEncoding: TEncoding;
+begin
+  LEncoding := TEncoding.UTF8;
+  LText := 'Hello, world!'; // User-supplied Unicode text
+  LErrCorLvl := TQrCode.TEcc.eccLow; // Error correction level
+  // Make the QR Code symbol
+  LQrCode := TQrCode.EncodeText(LText, LErrCorLvl, LEncoding);
+  WriteQrCodeToFile(LQrCode, 10, 4, 'hello-world-QR');
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.DoBasicDemoAndChangeColor;
+var
+  LText: String;
+  LErrCorLvl: TQrCode.TEcc;
+  LQrCode: IQrCode;
+  LEncoding: TEncoding;
+begin
+  LEncoding := TEncoding.UTF8;
+  LText := 'Hello, world!'; // User-supplied Unicode text
+  LErrCorLvl := TQrCode.TEcc.eccLow; // Error correction level
+  // Make the QR Code symbol
+  LQrCode := TQrCode.EncodeText(LText, LErrCorLvl, LEncoding);
+  LQrCode.BackgroundColor := HTMLColorToTAlphaColor('FFA500');
+  LQrCode.ForegroundColor := HTMLColorToTAlphaColor('000000');
+  WriteQrCodeToFile(LQrCode, 10, 4, 'hello-world-orange-background-QR');
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.DoSegmentDemo;
+const
+  // Kanji mode encoding (13 bits per character)
+  kanjiChars: array [0 .. 28] of Int32 = ($0035, $1002, $0FC0, $0AED, $0AD7,
+    $015C, $0147, $0129, $0059, $01BD, $018D, $018A, $0036, $0141, $0144, $0001,
+    $0000, $0249, $0240, $0249, $0000, $0104, $0105, $0113, $0115, $0000, $0208,
+    $01FF, $0008);
+var
+  LSilver0, LSilver1, LGolden0, LGolden1, LGolden2, LMadoka: String;
+  LBitBuffer: TBitBuffer;
+  LEncoding: TEncoding;
+  LQrCode: IQrCode;
+  LSegs: TQRCodeGenLibGenericArray<IQrSegment>;
+  LCIdx: Int32;
+begin
+  LEncoding := TEncoding.UTF8;
+  // Illustration "silver"
+  LSilver0 := 'THE SQUARE ROOT OF 2 IS 1.';
+  LSilver1 :=
+    '41421356237309504880168872420969807856967187537694807317667973799';
+  LQrCode := TQrCode.EncodeText(LSilver0 + LSilver1, TQrCode.TEcc.eccLow,
+    LEncoding);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'sqrt2-monolithic-QR');
+
+  LSegs := TQRCodeGenLibGenericArray<IQrSegment>.Create
+    (TQrSegment.MakeAlphanumeric(LSilver0), TQrSegment.MakeNumeric(LSilver1));
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccLow);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'sqrt2-segmented-QR');
+
+  // Illustration "golden"
+  LGolden0 := 'Golden ratio φ = 1.';
+  LGolden1 :=
+    '6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374';
+  LGolden2 := '......';
+  LQrCode := TQrCode.EncodeText(LGolden0 + LGolden1 + LGolden2,
+    TQrCode.TEcc.eccLow, LEncoding);
+  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-monolithic-QR.png');
+
+  LSegs := TQRCodeGenLibGenericArray<IQrSegment>.Create
+    (TQrSegment.MakeBytes(TConverters.ConvertStringToBytes(LGolden0, LEncoding)
+    ), TQrSegment.MakeNumeric(LGolden1), TQrSegment.MakeAlphanumeric(LGolden2));
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccLow);
+  WriteQrCodeToFile(LQrCode, 8, 5, 'phi-segmented-QR');
+
+  // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters
+  LMadoka := '「魔法少女まどか☆マギカ」って、 ИАИ desu κα?';
+  LQrCode := TQrCode.EncodeText(LMadoka, TQrCode.TEcc.eccLow, LEncoding);
+  WriteQrCodeToFile(LQrCode, 9, 4, 'madoka-utf8-QR');
+
+  LBitBuffer := TBitBuffer.Create();
+  for LCIdx in kanjiChars do
+  begin
+    LBitBuffer.AppendBits(LCIdx, 13);
+  end;
+  LSegs := TQRCodeGenLibGenericArray<IQrSegment>.Create
+    (TQrSegment.Create(TQrSegmentMode.qsmKanji, System.Length(kanjiChars),
+    LBitBuffer.Data, LBitBuffer.bitLength) as IQrSegment);
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccLow);
+  WriteQrCodeToFile(LQrCode, 9, 4, 'madoka-kanji-QR');
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.DoMaskDemo;
+var
+  LQrCode: IQrCode;
+  LSegs: TQRCodeGenLibGenericArray<IQrSegment>;
+  LEncoding: TEncoding;
+begin
+  LEncoding := TEncoding.UTF8;
+  // Project Nayuki URL
+  LSegs := TQrSegment.MakeSegments('https://www.nayuki.io/', LEncoding);
+  // Automatic mask
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccHigh,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, -1, true);
+  WriteQrCodeToFile(LQrCode, 8, 6, 'project-nayuki-automask-QR');
+  // Force mask 3
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccHigh,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, 3, true);
+  WriteQrCodeToFile(LQrCode, 8, 6, 'project-nayuki-mask3-QR');
+
+  // Chinese text as UTF-8
+  LSegs := TQrSegment.MakeSegments
+    ('維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫',
+    LEncoding);
+  // Force mask 0
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccMedium,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, 0, true);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'unicode-mask0-QR');
+  // Force mask 1
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccMedium,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, 1, true);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'unicode-mask1-QR');
+  // Force mask 5
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccMedium,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, 5, true);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'unicode-mask5-QR');
+  // Force mask 7
+  LQrCode := TQrCode.EncodeSegments(LSegs, TQrCode.TEcc.eccMedium,
+    TQrCode.MIN_VERSION, TQrCode.MAX_VERSION, 7, true);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'unicode-mask7-QR');
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.DoVarietyDemo;
+var
+  LQrCode: IQrCode;
+  LEncoding: TEncoding;
+begin
+  LEncoding := TEncoding.UTF8;
+  // Numeric mode encoding (3.33 bits per digit)
+  LQrCode := TQrCode.EncodeText
+    ('314159265358979323846264338327950288419716939937510',
+    TQrCode.TEcc.eccMedium, LEncoding);
+  WriteQrCodeToFile(LQrCode, 13, 1, 'pi-digits-QR');
+
+  // Alphanumeric mode encoding (5.5 bits per character)
+  LQrCode := TQrCode.EncodeText
+    ('DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/',
+    TQrCode.TEcc.eccHigh, LEncoding);
+  WriteQrCodeToFile(LQrCode, 10, 2, 'alphanumeric-QR');
+
+  // Unicode text as UTF-8
+  LQrCode := TQrCode.EncodeText('こんにちwa、世界! αβγδ', TQrCode.TEcc.eccQuartile,
+    LEncoding);
+  WriteQrCodeToFile(LQrCode, 10, 3, 'unicode-QR');
+
+  // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland)
+
+  LQrCode := TQrCode.EncodeText
+    ('Alice was beginning to get very tired of sitting by her sister on the bank, '
+    + 'and of having nothing to do: once or twice she had peeped into the book her sister was reading, '
+    + 'but it had no pictures or conversations in it, ''and what is the use of a book,'' thought Alice '
+    + '''without pictures or conversations?'' So she was considering in her own mind (as well as she could, '
+    + 'for the hot day made her feel very sleepy and stupid), whether the pleasure of making a '
+    + 'daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly '
+    + 'a White Rabbit with pink eyes ran close by her.',
+    TQrCode.TEcc.eccQuartile, LEncoding);
+  WriteQrCodeToFile(LQrCode, 6, 10, 'alice-wonderland-QR');
+
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.RunAllDemos;
+begin
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Started "DoBasicDemo"');
+  DoBasicDemo();
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Finished "DoBasicDemo"');
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add
+    ('Started "DoBasicDemoAndChangeColor"');
+  DoBasicDemoAndChangeColor();
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add
+    ('Finished "DoBasicDemoAndChangeColor"');
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Started "DoVarietyDemo"');
+  DoVarietyDemo();
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Finished "DoVarietyDemo"');
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Started "DoSegmentDemo"');
+  DoSegmentDemo();
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Finished "DoSegmentDemo"');
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Started "DoMaskDemo"');
+  DoMaskDemo();
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add('Finished "DoMaskDemo"');
+
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add(sLineBreak);
+  QRCodeGeneratorFMXDemoForm.mmoLogger.Lines.Add
+    ('Finished Executing All Demos');
+end;
+
+class procedure TQrCodeGeneratorDemoFMX.WriteQrCodeToFile
+  (const AQrCode: IQrCode; AScale, ABorder: Int32; const AFileName: String);
+const
+  FolderName: String = 'Assets';
+var
+  LFilePath: String;
+  LBitmap: TBitmap;
+begin
+  LFilePath := ExtractFilePath(ParamStr(0));
+  LFilePath := IncludeTrailingPathDelimiter(LFilePath);
+  LFilePath := IncludeTrailingPathDelimiter(LFilePath) + FolderName;
+  LFilePath := IncludeTrailingPathDelimiter(LFilePath);
+
+  if not DirectoryExists(LFilePath) then
+  begin
+    if not ForceDirectories(LFilePath) then
+    begin
+      // break out since we cannot create our "Assets" directory.
+      ShowMessage(Format('Error creating our "%s" directory.', [LFilePath]));
+      Exit;
+    end;
+  end;
+  LFilePath := LFilePath + AFileName;
+  // create bmp
+  LBitmap := AQrCode.ToBmpImage(AScale, ABorder);
+  try
+    try
+      // save bmp
+      LBitmap.SaveToFile(LFilePath + '.bmp');
+      // save jpeg
+      LBitmap.SaveToFile(LFilePath + '.jpg');
+      // save png
+      LBitmap.SaveToFile(LFilePath + '.png');
+      AQrCode.ToSvgFile(ABorder, LFilePath + '.svg');
+    except
+      raise;
+    end;
+  finally
+    LBitmap.Free;
+  end;
+end;
+
+end.

+ 1 - 1
QRCodeGenLib/src/Include/QRCodeGenLib.inc

@@ -10,7 +10,6 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-
  {$DEFINE DELPHI}
  {$DEFINE DELPHI}
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
@@ -125,6 +124,7 @@
 {$WARN COMBINING_SIGNED_UNSIGNED64 OFF}
 {$WARN COMBINING_SIGNED_UNSIGNED64 OFF}
 {$ENDIF}
 {$ENDIF}
 
 
+{.$DEFINE Framework_FMX} // enable to force FMX mode
 {$IFDEF Framework_FMX}
 {$IFDEF Framework_FMX}
 {$DEFINE FMX}
 {$DEFINE FMX}
 {$ELSE}
 {$ELSE}

+ 17 - 6
QRCodeGenLib/src/Interfaces/QlpIQrCode.pas

@@ -9,6 +9,9 @@ uses
   Vcl.Graphics,
   Vcl.Graphics,
   Vcl.Imaging.jpeg, // for VCL JPEG Support
   Vcl.Imaging.jpeg, // for VCL JPEG Support
   Vcl.Imaging.pngimage, // for VCL PNG Support
   Vcl.Imaging.pngimage, // for VCL PNG Support
+{$ELSEIF DEFINED(FMX)}
+  FMX.Graphics,
+  System.UITypes,
 {$ELSEIF DEFINED(LCL)}
 {$ELSEIF DEFINED(LCL)}
   Graphics,
   Graphics,
 {$IFEND}
 {$IFEND}
@@ -26,13 +29,19 @@ type
     property Mask: Int32 read GetMask;
     property Mask: Int32 read GetMask;
     function GetModules: TQRCodeGenLibInt32Array;
     function GetModules: TQRCodeGenLibInt32Array;
     property Modules: TQRCodeGenLibInt32Array read GetModules;
     property Modules: TQRCodeGenLibInt32Array read GetModules;
-    function GetBackgroundColor: TColor;
-    procedure SetBackgroundColor(const AColor: TColor);
-    property BackgroundColor: TColor read GetBackgroundColor
+    function GetBackgroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX};
+    procedure SetBackgroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX});
+    property BackgroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX} read GetBackgroundColor
       write SetBackgroundColor;
       write SetBackgroundColor;
-    function GetForegroundColor: TColor;
-    procedure SetForegroundColor(const AColor: TColor);
-    property ForegroundColor: TColor read GetForegroundColor
+    function GetForegroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX};
+    procedure SetForegroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX});
+    property ForegroundColor:
+    {$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX} read GetForegroundColor
       write SetForegroundColor;
       write SetForegroundColor;
 
 
     /// <summary>
     /// <summary>
@@ -82,6 +91,7 @@ type
     /// </remarks>
     /// </remarks>
     function ToBmpImage(AScale, ABorder: Int32): TBitmap;
     function ToBmpImage(AScale, ABorder: Int32): TBitmap;
 
 
+    {$IFNDEF FMX}
     /// <summary>
     /// <summary>
     /// Returns a jpeg image depicting this QR Code, with the specified
     /// Returns a jpeg image depicting this QR Code, with the specified
     /// module scale and border modules. For example, ToBmpImage(scale=10,
     /// module scale and border modules. For example, ToBmpImage(scale=10,
@@ -138,6 +148,7 @@ type
     /// </remarks>
     /// </remarks>
     function ToPngImage(AScale, ABorder: Int32):
     function ToPngImage(AScale, ABorder: Int32):
 {$IFDEF FPC}TPortableNetworkGraphic{$ELSE}TPngImage{$ENDIF FPC};
 {$IFDEF FPC}TPortableNetworkGraphic{$ELSE}TPngImage{$ENDIF FPC};
+{$ENDIF FMX}
 
 
     /// <summary>
     /// <summary>
     /// Returns a string of SVG code for an image depicting this QR Code,
     /// Returns a string of SVG code for an image depicting this QR Code,

+ 122 - 14
QRCodeGenLib/src/QRCodeGen/QlpQrCode.pas

@@ -12,6 +12,11 @@ uses
   Vcl.Graphics,
   Vcl.Graphics,
   Vcl.Imaging.jpeg, // for VCL JPEG Support
   Vcl.Imaging.jpeg, // for VCL JPEG Support
   Vcl.Imaging.pngimage, // for VCL PNG Support
   Vcl.Imaging.pngimage, // for VCL PNG Support
+{$ELSEIF DEFINED(FMX)}
+  FMX.Graphics,
+  FMX.Utils,
+  UIConsts,
+  UITypes,
 {$ELSEIF DEFINED(LCL)}
 {$ELSEIF DEFINED(LCL)}
   Graphics,
   Graphics,
   Interfaces, // Added so that the LCL will Initialize the WidgetSet
   Interfaces, // Added so that the LCL will Initialize the WidgetSet
@@ -138,16 +143,21 @@ type
     /// </summary>
     /// </summary>
     FErrorCorrectionLevel: TEcc;
     FErrorCorrectionLevel: TEcc;
     FModules: TQRCodeGenLibInt32Array;
     FModules: TQRCodeGenLibInt32Array;
-    FBackgroundColor, FForegroundColor: TColor;
+    FBackgroundColor, FForegroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX};
 
 
     function GetVersion: Int32; inline;
     function GetVersion: Int32; inline;
     function GetSize: Int32; inline;
     function GetSize: Int32; inline;
     function GetMask: Int32; inline;
     function GetMask: Int32; inline;
     function GetModules: TQRCodeGenLibInt32Array; inline;
     function GetModules: TQRCodeGenLibInt32Array; inline;
-    function GetBackgroundColor: TColor; inline;
-    function GetForegroundColor: TColor; inline;
-    procedure SetBackgroundColor(const AColor: TColor); inline;
-    procedure SetForegroundColor(const AColor: TColor); inline;
+    function GetBackgroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX}; inline;
+    function GetForegroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX}; inline;
+    procedure SetBackgroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX}); inline;
+    procedure SetForegroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX}); inline;
 
 
     // Draws two copies of the format bits (with its own error correction code)
     // Draws two copies of the format bits (with its own error correction code)
     // based on the given mask and this object's error correction level field.
     // based on the given mask and this object's error correction level field.
@@ -194,12 +204,16 @@ type
 {$IFDEF VCL}
 {$IFDEF VCL}
     function ToBmpImageInternalVCL(AScale, ABorder: Int32): TBitmap;
     function ToBmpImageInternalVCL(AScale, ABorder: Int32): TBitmap;
 {$ENDIF VCL}
 {$ENDIF VCL}
+{$IFDEF FMX}
+    function ToBmpImageInternalFMX(AScale, ABorder: Int32): TBitmap;
+{$ENDIF FMX}
     // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
     // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
     // QR Code of the given version number and error correction level, with remainder bits discarded.
     // QR Code of the given version number and error correction level, with remainder bits discarded.
     // This stateless pure function could be implemented as a (40*4)-cell lookup table.
     // This stateless pure function could be implemented as a (40*4)-cell lookup table.
     class function GetNumDataCodeWords(AVersion: Int32; AEcl: TEcc)
     class function GetNumDataCodeWords(AVersion: Int32; AEcl: TEcc)
       : Int32; inline;
       : Int32; inline;
 
 
+{$IFNDEF FMX}
     class function GetRValue(Argb: UInt32): Byte; static; inline;
     class function GetRValue(Argb: UInt32): Byte; static; inline;
     class function GetGValue(Argb: UInt32): Byte; static; inline;
     class function GetGValue(Argb: UInt32): Byte; static; inline;
     class function GetBValue(Argb: UInt32): Byte; static; inline;
     class function GetBValue(Argb: UInt32): Byte; static; inline;
@@ -217,6 +231,22 @@ type
     /// </returns>
     /// </returns>
     class function TColorToHTMLColorHex(const AColor: TColor): String; inline;
     class function TColorToHTMLColorHex(const AColor: TColor): String; inline;
 
 
+{$ELSE}
+    /// <summary>
+    /// Convert a Delphi FireMonkey <c>TAlphaColor</c> to <c>HTML</c> Color code in
+    /// Hex <c>.</c>
+    /// </summary>
+    /// <param name="AColor">
+    /// the <c>TAlphaColor</c> to convert
+    /// </param>
+    /// <returns>
+    /// returns a string containing the <c>HTML</c> Color code representation
+    /// of the <c>TAlphaColor</c> parameter in Hex
+    /// </returns>
+    class function TAlphaColorToHTMLColorHex(const AColor: TAlphaColor)
+      : String; inline;
+
+{$ENDIF FMX}
   public
   public
 
 
     const
     const
@@ -296,14 +326,16 @@ type
     /// property for getting/setting the background color of the QRCode <br />
     /// property for getting/setting the background color of the QRCode <br />
     /// Object <br />
     /// Object <br />
     /// </summary>
     /// </summary>
-    property BackgroundColor: TColor read GetBackgroundColor
+    property BackgroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX} read GetBackgroundColor
       write SetBackgroundColor;
       write SetBackgroundColor;
 
 
     /// <summary>
     /// <summary>
     /// property for getting/setting the foreground color of the QRCode
     /// property for getting/setting the foreground color of the QRCode
     /// Object
     /// Object
     /// </summary>
     /// </summary>
-    property ForegroundColor: TColor read GetForegroundColor
+    property ForegroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX} read GetForegroundColor
       write SetForegroundColor;
       write SetForegroundColor;
 
 
     /// <summary>
     /// <summary>
@@ -334,6 +366,7 @@ type
     /// </remarks>
     /// </remarks>
     function ToBmpImage(AScale, ABorder: Int32): TBitmap;
     function ToBmpImage(AScale, ABorder: Int32): TBitmap;
 
 
+{$IFNDEF FMX}
     /// <summary>
     /// <summary>
     /// Returns a jpeg image depicting this QR Code, with the specified
     /// Returns a jpeg image depicting this QR Code, with the specified
     /// module scale and border modules. For example, ToBmpImage(scale=10,
     /// module scale and border modules. For example, ToBmpImage(scale=10,
@@ -390,7 +423,7 @@ type
     /// </remarks>
     /// </remarks>
     function ToPngImage(AScale, ABorder: Int32):
     function ToPngImage(AScale, ABorder: Int32):
 {$IFDEF FPC}TPortableNetworkGraphic{$ELSE}TPngImage{$ENDIF FPC};
 {$IFDEF FPC}TPortableNetworkGraphic{$ELSE}TPngImage{$ENDIF FPC};
-
+{$ENDIF FMX}
     /// <summary>
     /// <summary>
     /// Returns a string of SVG code for an image depicting this QR Code,
     /// Returns a string of SVG code for an image depicting this QR Code,
     /// with the specified number of border modules. The string always uses
     /// with the specified number of border modules. The string always uses
@@ -561,6 +594,8 @@ implementation
 
 
 { TQrCode }
 { TQrCode }
 
 
+{$IFNDEF FMX}
+
 class function TQrCode.GetRValue(Argb: UInt32): Byte;
 class function TQrCode.GetRValue(Argb: UInt32): Byte;
 begin
 begin
   Result := Byte(Argb);
   Result := Byte(Argb);
@@ -582,6 +617,17 @@ begin
     GetGValue(ColorToRGB(AColor)), GetBValue(ColorToRGB(AColor))]);
     GetGValue(ColorToRGB(AColor)), GetBValue(ColorToRGB(AColor))]);
 end;
 end;
 
 
+{$ELSE}
+
+class function TQrCode.TAlphaColorToHTMLColorHex(const AColor
+  : TAlphaColor): String;
+begin
+  Result := Format('%.2x%.2x%.2x', [TAlphaColorRec(AColor).R,
+    TAlphaColorRec(AColor).G, TAlphaColorRec(AColor).B]);
+end;
+
+{$ENDIF FMX}
+
 function TQrCode.GetVersion: Int32;
 function TQrCode.GetVersion: Int32;
 begin
 begin
   Result := FVersion;
   Result := FVersion;
@@ -898,8 +944,8 @@ begin
   LAllCodewords := AddEccAndInterleave(ADataCodewords);
   LAllCodewords := AddEccAndInterleave(ADataCodewords);
   DrawCodeWords(LTpl.DataOutputBitIndexes, LAllCodewords);
   DrawCodeWords(LTpl.DataOutputBitIndexes, LAllCodewords);
   FMask := HandleConstructorMasking(LTpl.Masks, AMask);
   FMask := HandleConstructorMasking(LTpl.Masks, AMask);
-  FBackgroundColor := clWhite;
-  FForegroundColor := clBlack;
+  FBackgroundColor := {$IFNDEF FMX}clWhite{$ELSE}claWhite{$ENDIF FMX};
+  FForegroundColor := {$IFNDEF FMX}clBlack{$ELSE}claBlack{$ENDIF FMX};
 end;
 end;
 
 
 procedure TQrCode.SetModule(Ax, Ay, ABlack: Int32);
 procedure TQrCode.SetModule(Ax, Ay, ABlack: Int32);
@@ -1038,6 +1084,55 @@ begin
   end;
   end;
 end;
 end;
 {$ENDIF VCL}
 {$ENDIF VCL}
+{$IFDEF FMX}
+
+function TQrCode.ToBmpImageInternalFMX(AScale, ABorder: Int32): TBitmap;
+var
+  LColumn, LRow: Int32;
+  LDoColor: Boolean;
+  LBrushColor: TColor;
+  LForegroundColor, LBackgroundColor: TColor;
+  LScanLine: PAlphaColorArray;
+  LBitData: TBitmapData;
+begin
+  Result := TBitmap.Create;
+  Result.SetSize((FSize + (ABorder * 2)) * AScale, (FSize + (ABorder * 2))
+    * AScale);
+  LForegroundColor := FForegroundColor;
+  LBackgroundColor := FBackgroundColor;
+
+  if Result.Map(TMapAccess.Write, LBitData) then
+  begin
+    try
+      for LColumn := 0 to System.Pred(Result.Height) do
+      begin
+        LScanLine := LBitData.GetScanLine(LColumn);
+        for LRow := 0 to System.Pred(Result.Width) do
+        begin
+          LDoColor := GetModule((LRow div AScale) - ABorder,
+            (LColumn div AScale) - ABorder);
+          if LDoColor then
+          begin
+            LBrushColor := LForegroundColor;
+          end
+          else
+          begin
+            LBrushColor := LBackgroundColor;
+          end;
+          // Slow !!!
+         // LBitData.SetPixel(LRow, LColumn, LBrushColor);
+          LScanLine^[LRow] := LBrushColor;
+        end;
+
+      end;
+
+    finally
+      Result.Unmap(LBitData);
+    end;
+  end;
+
+end;
+{$ENDIF FMX}
 
 
 function TQrCode.ToBmpImage(AScale, ABorder: Int32): TBitmap;
 function TQrCode.ToBmpImage(AScale, ABorder: Int32): TBitmap;
 begin
 begin
@@ -1046,10 +1141,13 @@ begin
   Result := ToBmpImageInternalLCL(AScale, ABorder);
   Result := ToBmpImageInternalLCL(AScale, ABorder);
 {$ELSEIF DEFINED(VCL)}
 {$ELSEIF DEFINED(VCL)}
   Result := ToBmpImageInternalVCL(AScale, ABorder);
   Result := ToBmpImageInternalVCL(AScale, ABorder);
+{$ELSEIF DEFINED(FMX)}
+  Result := ToBmpImageInternalFMX(AScale, ABorder);
 {$ELSE}
 {$ELSE}
 {$MESSAGE ERROR 'This UI Framework is not supported at the moment.'}
 {$MESSAGE ERROR 'This UI Framework is not supported at the moment.'}
 {$IFEND}
 {$IFEND}
 end;
 end;
+{$IFNDEF FMX}
 
 
 function TQrCode.ToJpegImage(AScale, ABorder: Int32): TJPEGImage;
 function TQrCode.ToJpegImage(AScale, ABorder: Int32): TJPEGImage;
 var
 var
@@ -1078,6 +1176,7 @@ begin
     LBitmap.Free;
     LBitmap.Free;
   end;
   end;
 end;
 end;
+{$ENDIF FMX}
 
 
 function TQrCode.ToSvgString(ABorder: Int32): String;
 function TQrCode.ToSvgString(ABorder: Int32): String;
 var
 var
@@ -1091,8 +1190,13 @@ begin
     raise EArgumentInvalidQRCodeGenLibException.CreateRes(@SBorderNegative);
     raise EArgumentInvalidQRCodeGenLibException.CreateRes(@SBorderNegative);
   end;
   end;
   LBorder := ABorder;
   LBorder := ABorder;
+{$IFNDEF FMX}
   LForegroundColor := TColorToHTMLColorHex(FForegroundColor);
   LForegroundColor := TColorToHTMLColorHex(FForegroundColor);
   LBackgroundColor := TColorToHTMLColorHex(FBackgroundColor);
   LBackgroundColor := TColorToHTMLColorHex(FBackgroundColor);
+{$ELSE}
+  LForegroundColor := TAlphaColorToHTMLColorHex(FForegroundColor);
+  LBackgroundColor := TAlphaColorToHTMLColorHex(FBackgroundColor);
+{$ENDIF FMX}
   LStringList := TStringList.Create;
   LStringList := TStringList.Create;
   LStringList.LineBreak := '';
   LStringList.LineBreak := '';
   try
   try
@@ -1343,22 +1447,26 @@ begin
   Result := EncodeSegments(TQrSegment.MakeSegments(AText, AEncoding), AEcl);
   Result := EncodeSegments(TQrSegment.MakeSegments(AText, AEncoding), AEcl);
 end;
 end;
 
 
-function TQrCode.GetBackgroundColor: TColor;
+function TQrCode.GetBackgroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX};
 begin
 begin
   Result := FBackgroundColor;
   Result := FBackgroundColor;
 end;
 end;
 
 
-function TQrCode.GetForegroundColor: TColor;
+function TQrCode.GetForegroundColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX};
 begin
 begin
   Result := FForegroundColor;
   Result := FForegroundColor;
 end;
 end;
 
 
-procedure TQrCode.SetBackgroundColor(const AColor: TColor);
+procedure TQrCode.SetBackgroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX});
 begin
 begin
   FBackgroundColor := AColor;
   FBackgroundColor := AColor;
 end;
 end;
 
 
-procedure TQrCode.SetForegroundColor(const AColor: TColor);
+procedure TQrCode.SetForegroundColor(const AColor:
+{$IFNDEF FMX}TColor{$ELSE}TAlphaColor{$ENDIF FMX});
 begin
 begin
   FForegroundColor := AColor;
   FForegroundColor := AColor;
 end;
 end;

+ 2 - 4
README.md

@@ -10,7 +10,7 @@ Features
 Core features:
 Core features:
 
 
 * Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard
 * Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard
-* Output formats: Raw modules/pixels of the QR symbol, SVG XML string/file, `ImageObject`(`bmp`, `jpg` and `png`).
+* Output formats: Raw modules/pixels of the QR symbol, SVG XML string/file, `ImageObject`(`bmp` (`jpg` and `png`) for `VCL` and `LCL` only).
 * Encodes numeric and special-alphanumeric text in less space than general text
 * Encodes numeric and special-alphanumeric text in less space than general text
 * Ability to change the backgound and foreground colors of the generated QRCode.
 * Ability to change the backgound and foreground colors of the generated QRCode.
 * Open source code under the permissive MIT License
 * Open source code under the permissive MIT License
@@ -34,9 +34,7 @@ Manual parameters:
     
     
     VCL Framework (Delphi)
     VCL Framework (Delphi)
     
     
-    *FMX (Delphi).
-    
-   Experimental FMX support can be found [here](https://github.com/Xor-el/QRCodeGenLib4Pascal/tree/ExperimentalFMXSupport)
+    FMX (Support is currently experimental, to use, enable the define "{.$DEFINE Framework_FMX}" in "QRCodeGenLib.inc").
 
 
 **Installing the Library.**
 **Installing the Library.**