{ * Copyright 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * Original Author: bbrown@google.com (Brian Brown) * Delphi Implementation by E. Spelt and K. Gossens } unit ZXing.ReadResult; interface uses System.SysUtils, Generics.Collections, ZXing.ResultPoint, ZXing.ResultMetadataType, ZXing.BarcodeFormat, ZXing.ByteSegments; type IMetaData = Interface ['{27AEB2C5-D775-44C6-9816-3E69025CA57C}'] end; IStringMetadata = interface(IMetaData) ['{8073F897-30AD-49B7-AE0B-B187D3373163}'] function Value:String; end; IIntegerMetadata = interface(IMetaData) ['{CA60A23A-57ED-4C8E-9886-4F23B832A90C}'] function Value:Integer; end; IByteSegmentsMetadata = interface(IMetaData) ['{CA60A23A-57ED-4C8E-9886-4F23B832A90C}'] function Value:IByteSegments; end; /// /// represents the metadata contained in a TReadResult and provides the /// helping functions needed to create them /// TResultMetaData = class(TDictionary) public constructor Create; class function CreateStringMetadata(const Value:string) :IStringMetaData; class function CreateIntegerMetadata(const Value:integer) :IIntegerMetaData; class function CreateByteSegmentsMetadata(const Value:IByteSegments) :IByteSegmentsMetadata; end; TReadResult = class private FText: string; FTimeStamp: TDateTime; FResultMetadata: TResultMetaData; FRawBytes: TArray; FResultPoints: TArray; FFormat: TBarcodeFormat; procedure SetText(const AValue: String); procedure SetMetaData( const Value: TResultMetadata); public /// /// Initializes a new instance of the class. /// /// The text. /// The raw bytes. /// The result points. /// The format. constructor Create(const text: string; const rawBytes: TArray; const resultPoints: TArray; const format: TBarcodeFormat); overload; /// /// Initializes a new instance of the class. /// /// The text. /// The raw bytes. /// The result points. /// The format. /// The timestamp. constructor Create(const text: string; const rawBytes: TArray; const resultPoints: TArray; const format: TBarcodeFormat; const timeStamp: TDateTime); overload; destructor Destroy; override; function ToString: String; override; // we need a "write" procedure accessor because we need to properly deallocate // existing instance if we overwrite it with another one property ResultMetaData: TResultMetadata read FResultMetadata write SetMetaData; /// /// Adds one metadata to the result /// /// The type. /// The value. procedure putMetadata(const ResultMetadataType: TResultMetadataType; const Value: IMetaData); /// /// Adds a list of metadata to the result /// /// The metadata. procedure putAllMetaData(const metaData: TResultMetadata); /// /// Adds the result points. /// /// The new points. procedure addResultPoints(const newPoints: TArray); /// raw text encoded by the barcode, if applicable, otherwise null property text: String read FText write SetText; /// raw bytes encoded by the barcode, if applicable, otherwise null property rawBytes: TArray read FRawBytes write FRawBytes; /// /// points related to the barcode in the image. These are typically points /// identifying finder patterns or the corners of the barcode. The exact meaning is /// specific to the type of barcode that was decoded. /// property resultPoints: TArray read FResultPoints write FResultPoints; /// {@link TBarcodeFormat} representing the format of the barcode that was decoded property BarcodeFormat: TBarcodeFormat read FFormat write FFormat; /// /// Gets the timestamp. /// property timeStamp: TDateTime read FTimeStamp; end; implementation {$REGION 'IMetaData implementations'} { TStringMetadata } type TStringMetadata = class(TInterfacedObject,IMetaData,IStringMetadata) strict private FValue: String; function Value: String; private constructor Create(const AValue: String); end; function TStringMetadata.Value: String; begin result := FValue end; constructor TStringMetadata.Create(const AValue: string); begin inherited Create; FValue := AValue; end; { TIntegerMetadata } type TIntegerMetadata = class(TInterfacedObject,IMetaData,IIntegerMetadata) strict private FValue: Integer; function Value: Integer; private constructor Create(const AValue: Integer); end; function TIntegerMetadata.Value: Integer; begin result := FValue end; constructor TIntegerMetadata.Create(const AValue: Integer); begin inherited Create; FValue := AValue; end; { TByteSegmentsMetadata } type TByteSegmentsMetadata = class(TInterfacedObject,IMetaData,IByteSegmentsMetadata) strict private FValue: IByteSegments; function Value: IByteSegments; private constructor Create(const AValue: IByteSegments); end; function TByteSegmentsMetadata.Value: IByteSegments; begin result := FValue end; constructor TByteSegmentsMetadata.Create(const AValue: IByteSegments); begin inherited Create; FValue := AValue; end; { TResultMetadata } constructor TResultMetaData.Create; begin inherited Create; end; class function TResultMetadata.CreateStringMetadata(const Value:string) :IStringMetaData; begin result := TStringMetadata.Create(Value); end; class function TResultMetaData.CreateByteSegmentsMetadata( const Value: IByteSegments): IByteSegmentsMetadata; begin result := TByteSegmentsMetadata.Create(value); end; class function TResultMetadata.CreateIntegerMetadata(const Value:integer) :IIntegerMetaData; begin result := TIntegerMetadata.Create(Value); end; {$ENDREGION 'IMetaData implementations'} { TReadResult } constructor TReadResult.Create(const text: String; const rawBytes: TArray; const resultPoints: TArray; const format: TBarcodeFormat); begin Self.Create(text, rawBytes, resultPoints, format, Now); end; constructor TReadResult.Create(const text: String; const rawBytes: TArray; const resultPoints: TArray; const format: TBarcodeFormat; const timeStamp: TDateTime); begin if ((text = '') and (rawBytes = nil)) then raise EArgumentException.Create('Text and bytes are null.'); SetText(text); FRawBytes := rawBytes; FResultPoints := resultPoints; FResultMetadata := nil; FFormat := format; FResultMetadata := nil; FTimeStamp := timeStamp; end; destructor TReadResult.Destroy; var i:Integer; begin for I := Low(FResultPoints) to High(FResultPoints) do begin FResultPoints[i] := nil; end; FResultPoints := nil; FRawBytes := nil; if FResultMetadata <> nil then begin FResultMetadata.Clear; FreeAndNil(FResultMetadata); end; inherited; end; // Added (KG): UTF-8 compatiblity procedure TReadResult.SetMetaData(const Value: TResultMetadata); begin if value = FResultMetadata then exit; // no change if FResultMetadata<>nil then FResultMetadata.Free; // we need to free existing object instance, for old-gen compilers FResultMetadata := Value; end; procedure TReadResult.SetText(const AValue: String); begin FText := AValue; end; procedure TReadResult.putMetadata(const ResultMetadataType: TResultMetadataType; const Value: IMetaData); begin if (FResultMetadata = nil) then FResultMetadata := TResultMetadata.Create(); FResultMetadata.AddOrSetValue(ResultMetadataType, Value); end; procedure TReadResult.putAllMetaData(const metaData: TResultMetadata); var key: TResultMetadataType; begin if (metaData <> nil) then begin if (FResultMetadata = nil) then FResultMetadata := TResultMetadata.Create(); for key in metaData.Keys do FResultMetadata.AddOrSetValue(key, metaData[key]); end; end; procedure TReadResult.addResultPoints(const newPoints: TArray); begin FResultPoints := FResultPoints + newPoints; end; /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// function TReadResult.ToString(): String; begin if (text = '') then Result := '[' + IntToStr(Length(rawBytes)) + ' bytes]' else Result := text; end; end.