diff --git a/components/lazbarcodes/demo/main.pas b/components/lazbarcodes/demo/main.pas index 33d5fc893..1f2684c4a 100644 --- a/components/lazbarcodes/demo/main.pas +++ b/components/lazbarcodes/demo/main.pas @@ -115,6 +115,7 @@ begin RegisterClass(TBarcodeAztec); RegisterClass(TBarcodeAztecRune); RegisterClass(TBarcodeDatamatrix); + RegisterClass(TBarcodeMaxiCode); end; @@ -410,6 +411,7 @@ begin child := Items.AddChildObject(node, 'Aztec', PChar('TBarcodeAztec')); child := Items.AddChildObject(node, 'Aztec Rune', PChar('TBarcodeAztecRune')); child := Items.AddChildObject(node, 'Data Matrix', PChar('TBarcodeDataMatrix')); + child := Items.AddChildObject(node, 'Maxicode (ISO 16023)', PChar('TBarcodeMaxiCode')); FullExpand; finally diff --git a/components/lazbarcodes/src/ubarcodes.pas b/components/lazbarcodes/src/ubarcodes.pas index f09eb85f3..c14bacb9a 100644 --- a/components/lazbarcodes/src/ubarcodes.pas +++ b/components/lazbarcodes/src/ubarcodes.pas @@ -209,7 +209,7 @@ type function CalcSymbolStart(ABorderWidth, AWhiteSpaceWidth: Integer): Integer; virtual; procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean); override; - procedure DrawBarcode(ADrawer: TBasicBarcodeDrawer; AFactor: Double); + procedure DrawBarcode(ADrawer: TBasicBarcodeDrawer; AFactor: Double); virtual; function GetLastLine: PZintRenderLine; procedure GetTextSize(const AText: String; out AWidth, AHeight: Integer); function InternalGenerate: Integer; override; @@ -605,13 +605,28 @@ type { TBarcodeMaxiCode } + TBarcodeMaxicodeMode = (mcmAuto=-1, mcmMode2=2, mcmMode3=3, mcmMode4=4, mcmMode5=5, mcmMode6); - TBarcodeMaxiCode = class(TBarcodeSquare) + TBarcodeMaxiCode = class(TSimpleBarcode) + private + FMode: TBarcodeMaxicodeMode; + procedure SetMode(AValue: TBarcodeMaxicodeMode); protected + function CalcFactor(AWidth, AHeight: Integer): Integer; override; + procedure CalcSize(AFactor: Integer; + out ATotalWidth, ATotalHeight, ASymbolWidth, ASymbolHeight, + ATextWidth, ATextHeight, ABorderWidth, AWhitespaceWidth: Integer); override; + procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; + WithThemeSpace: Boolean); override; + procedure DrawBarcode(ADrawer: TBasicBarcodeDrawer; AFactor: Double); override; + class function GetControlClassDefaultSize: TSize; override; function InternalGenerate: Integer; override; - procedure RenderSymbol(xLeft, yTop, ASymbolHeight, {%H-}ATextHeight, AFactor: Integer); override; + procedure RenderSymbol(xLeft, yTop, {%H-}ASymbolHeight, {%H-}ATextHeight, AFactor: Integer); override; + procedure SetRecommendedSymbolSizeParams; override; public constructor Create(AOwner: TComponent); override; + published + property Mode: TBarcodeMaxicodeMode read FMode write SetMode default mcmAuto; end; @@ -1381,7 +1396,7 @@ begin ADrawer.BackColor := ColorToRGB(FBackgroundColor); if FForegroundColor = clDefault then - ADrawer.TextColor := GetDefaultColor(dctFont) + ADrawer.BarColor := GetDefaultColor(dctFont) else ADrawer.BarColor := ColorToRGB(FForegroundColor); @@ -1410,7 +1425,7 @@ begin // Draw the lines (bars, bearing bars, box) line := FSymbol^.Rendered^.lines; - while Assigned(Line) do begin + while Assigned(line) do begin ADrawer.DrawBar( AFactor * line^.x, AFactor * line^.y, @@ -3050,7 +3065,7 @@ begin Result.CY := 88; end; -procedure TBarcodesquare.SetRecommendedSymbolSizeParams; +procedure TBarcodeSquare.SetRecommendedSymbolSizeParams; begin FScale := 0; FSymbolHeight := 0; @@ -3177,6 +3192,10 @@ end; { TBarcodeMaxiCode } +const + H_HEXAGON = 2.0/sqrt(3.0); + W_HEXAGON = 1.0; + constructor TBarcodeMaxiCode.Create(AOwner: TComponent); begin FBarcodeType := bctMaxiCode; @@ -3184,17 +3203,192 @@ begin inherited; + FMode := mcmAuto; FShowHumanReadableText := false; end; +{ Calculates the pixel multiplication factor to fill the entire control as much + as possible. Needed when FScale = 0. Considers only integer multiples of + pixels. For MaxiCode the aspect ratio (height/width) is constant 26.93mm/28.14mm.} +function TBarcodeMaxiCode.CalcFactor(AWidth, AHeight: Integer): Integer; +var + h, w: Double; + fx, fy: Double; +begin + h := H_HEXAGON * (FSymbol^.Rows + 2); + w := W_HEXAGON * (FSymbol^.Width + 2); + fx := AWidth/w; + fy := AHeight/h; + if fx < fy then + Result := round(fx) + else + Result := round(fy); + if Result = 0 then + Result := 1; +end; + + +{ Calculates the dimensions of the maxi code symgol. + The scaling factor has been applied. } +procedure TBarcodeMaxiCode.CalcSize(AFactor: Integer; + out ATotalWidth, ATotalHeight, ASymbolWidth, ASymbolHeight, + ATextWidth, ATextHeight, ABorderWidth, AWhitespaceWidth: Integer); +begin + // +2 for an empty hexagon around the symbol + ASymbolWidth := round(W_HEXAGON * (FSymbol^.Width + 2) * AFactor); + ASymbolHeight := round(H_HEXAGON * (FSymbol^.Rows + 2) * AFactor); + + // No human-readable text + ATextWidth := 0; + ATextHeight := 0; + + ABorderWidth := FMargin; + AWhitespaceWidth := 0; // No white-space + + ATotalWidth := ASymbolWidth + 2 * ABorderWidth; + ATotalHeight := ASymbolHeight + 2 * ABorderWidth; +end; + +procedure TBarcodeMaxiCode.CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; + WithThemeSpace: Boolean); +var + wtot, htot, wsym, hsym, wtxt, htxt, wb, wws: Integer; + factor: Integer; +begin + inherited; + if FScale = 0 then + factor := CalcFactor(ClientWidth, ClientHeight) + else + factor := FScale; + CalcSize(factor, wtot, htot, wsym, hsym, wtxt, htxt, wb, wws); + PreferredWidth := wtot; + PreferredHeight := htot; +end; + +procedure TBarcodeMaxiCode.DrawBarcode(ADrawer: TBasicBarcodeDrawer; AFactor: Double); +var + hexagon: PZintRenderHexagon; + wx: Double; +begin + // Prepare drawer + if FBackgroundColor = clDefault then + ADrawer.BackColor := GetDefaultColor(dctBrush) + else + ADrawer.BackColor := ColorToRGB(FBackgroundColor); + + if FForegroundColor = clDefault then + ADrawer.BarColor := GetDefaultColor(dctFont) + else + ADrawer.BarColor := ColorToRGB(FForegroundColor); + + // Start drawing, clear background + ADrawer.BeginDrawing; + + // Hexagon horizontal width + if FScale = 0 then + wx := AFactor * CalcFactor(ClientWidth, ClientHeight) + else + wx := AFactor * FScale; + + // Draw the hexagons + hexagon := FSymbol^.Rendered^.hexagons; + while Assigned(hexagon) do begin + ADrawer.DrawHexagon(hexagon^.x, hexagon^.y, wx); + hexagon := hexagon^.Next; + end; + + // Finish drawing + ADrawer.EndDrawing; +end; + +class function TBarcodeMaxiCode.GetControlClassDefaultSize: TSize; +begin + Result.CX := 88; + Result.CY := 88; +end; + function TBarcodeMaxiCode.InternalGenerate: Integer; begin - Move(FText[1], FSymbol^.Primary[0], Length(FText)); + FSymbol^.option_1 := ord(FMode); + + //Move(FText[1], FSymbol^.Primary[0], Length(FText)); Result := maxicode(FSymbol, @FText[1], Length(FText)); end; procedure TBarcodeMaxiCode.RenderSymbol(xLeft, yTop, ASymbolHeight, {%H-}ATextHeight, AFactor: Integer); +var + ring, last_ring: PZintRenderRing; + hexagon, last_hexagon: PZintRenderHexagon; + i, j: Integer; + x, y: Double; + xFactor, yFactor: Double; begin + // Hexagons + xFactor := H_HEXAGON * AFactor; + yFactor := W_HEXAGON * AFactor; + last_hexagon := nil; + for j := 0 to FSymbol^.Rows - 1 do + begin + y := yFactor * (j + 1) + yTop; + for i := 0 to FSymbol^.Width - 1 do + if module_is_set(FSymbol, j, i) then + begin + x := xFactor * (i + 1) + xLeft; + if odd(i) then + x := x + xFactor * 0.5; + hexagon := render_plot_create_hexagon(x, y); + render_plot_add_hexagon(FSymbol, hexagon, @last_hexagon); + end; + end; + + (* + h := ASymbolHeight - 2 * yTop; + w := h; + xc := ASymbolHeight div 2; + yc := ASymbolHeight div 2; + + ring := render_plot_create_ring(xc, yc, r, dr); + + + scaler := GL_CONST; // Converts from millimeters to the scale used by glabels + render^.width := 28.16 * scaler; + render^.height := 26.86 * scaler; + + // Central bullseye pattern + ring := render_plot_create_ring (13.64 * scaler, 13.43 * scaler, 0.85 * scaler, 0.67 * scaler); + render_plot_add_ring (symbol, ring, @last_ring); + ring := render_plot_create_ring (13.64 * scaler, 13.43 * scaler, 2.20 * scaler, 0.67 * scaler); + render_plot_add_ring (symbol, ring, @last_ring); + ring := render_plot_create_ring (13.64 * scaler, 13.43 * scaler, 3.54 * scaler, 0.67 * scaler); + render_plot_add_ring (symbol, ring, @last_ring); + + // Hexagons + for r := 0 to symbol^.rows-1 do + begin + for i := 0 to symbol^.width-1 do + if module_is_set(symbol,r, i) then + begin + if r and 1 <> 0 then + hexagon := render_plot_create_hexagon((i*0.88 + 1.76) * scaler, (r*0.76 + 0.76)*scaler) + else + hexagon := render_plot_create_hexagon((i*0.88 + 1.32) * scaler, (r*0.76 + 0.76)*scaler); + end; + end; + *) +end; + +procedure TBarcodeMaxicode.SetMode(AValue: TBarcodeMaxicodeMode); +begin + if FMode = AValue then exit; + FMode := AValue; + GenerateAndInvalidate; +end; + +procedure TBarcodeMaxiCode.SetRecommendedSymbolSizeParams; +begin + FScale := 4; + FSymbolHeight := 0; + FShowHumanReadableText := false; end; end. diff --git a/components/lazbarcodes/src/udrawers.pas b/components/lazbarcodes/src/udrawers.pas index 3af0bdbc5..2c25e9ee7 100644 --- a/components/lazbarcodes/src/udrawers.pas +++ b/components/lazbarcodes/src/udrawers.pas @@ -98,7 +98,7 @@ type procedure EndDrawing; override; procedure DrawBar(x1, y1, x2, y2: Double); override; procedure DrawCenteredText(x, y: Double; const AText: String); override; - procedure DrawHexagon(x, y, r: Double); override; + procedure DrawHexagon(x, y, wx: Double); override; procedure DrawRing(x, y, rOuter, rInner: Double); override; end; @@ -111,13 +111,15 @@ type end; const - HEXAGON: array[0..5] of TDblPoint = ( - (X: 1.0; Y: 0.0000000), - (X: 0.5; Y: 0.8660254), - (X:-0.5; Y: 0.8660254), - (X:-1.0; Y: 0.0000000), - (X:-0.5; Y:-0.8660254), - (X: 0.5; Y:-0.8660254) + H = 1.0 / sqrt(3.0); + HH = H + H; + HEXAGON: array[0..5] of TDblPoint = ( // 0 + (X: 0.0; Y: HH), // / \ + (X:-1.0; Y: H), // 1 5 + (X:-1.0; Y:-H), // | | + (X: 0.0; Y:-HH), // 2 4 + (X: 1.0; Y:-H), // \ / + (X: 1.0; Y: H) // 3 ); { TBasicBarcodeDrawer } @@ -410,7 +412,7 @@ begin FList.Add(Format('(%s) dup stringwidth pop 2 div neg -%.2f rmoveto show', [AText, 1.0*FFontSize], FFormatSettings)); end; -procedure TEpsBarcodeDrawer.DrawHexagon(x, y, r: Double); +procedure TEpsBarcodeDrawer.DrawHexagon(x, y, wx: Double); var P: array[0..5] of TDblPoint; s: String; @@ -419,8 +421,8 @@ var begin for i := 0 to 5 do begin - P[i].X := x + HEXAGON[i].X*r; - P[i].Y := y + HEXAGON[i].Y*r; + P[i].X := x + HEXAGON[i].X*wx; + P[i].Y := y + HEXAGON[i].Y*wx; end; if FStoredColor <> FBarColor then