mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-30 06:42:49 +02:00
customdrawn-android: Finishes the initial implementation of text rendering, it works ok for a very initial support. Improves the AlphaBlend method in TLazCanvas to be more optimized and support a custom source position.
git-svn-id: trunk@34138 -
This commit is contained in:
parent
2b4adf30f7
commit
446ffaa84b
@ -81,6 +81,7 @@ public class LCLActivity extends Activity
|
||||
{
|
||||
Paint localpaint = new Paint();
|
||||
Rect localbounds = new Rect();
|
||||
localpaint.setTextSize(18);
|
||||
localpaint.getTextBounds(lcltext, 0, lcltext.length(), localbounds);
|
||||
lclwidth = localbounds.width();
|
||||
lclheight = localbounds.height();
|
||||
@ -93,7 +94,11 @@ public class LCLActivity extends Activity
|
||||
lclbitmap = Bitmap.createBitmap(lclwidth, lclheight, Bitmap.Config.ARGB_8888);
|
||||
Canvas localcanvas = new Canvas(lclbitmap);
|
||||
Paint localpaint = new Paint();
|
||||
localcanvas.drawText(lcltext, 0, 0, localpaint);
|
||||
localpaint.setColor(Color.BLACK);
|
||||
localpaint.setTextSize(18);
|
||||
localpaint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
localcanvas.drawColor(Color.TRANSPARENT); // TRANSPARENT
|
||||
localcanvas.drawText(lcltext, 0, lclheight, localpaint);
|
||||
}
|
||||
|
||||
// LCLType definitions
|
||||
@ -172,6 +177,7 @@ public class LCLActivity extends Activity
|
||||
public int lclbutton2;
|
||||
public int lclbutton3;
|
||||
public Bitmap lclbitmap;
|
||||
public int lcltextsize;
|
||||
|
||||
static
|
||||
{
|
||||
|
@ -31,4 +31,8 @@
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
// Default options for various backends
|
||||
{$ifdef CD_Android}
|
||||
{$define CD_UseNativeText}
|
||||
{$endif}
|
||||
|
||||
|
@ -86,7 +86,8 @@ procedure HideForm(ACDForm: TCDNonNativeForm);
|
||||
|
||||
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
||||
AData: Pointer = nil; AForceUpdate: Boolean = False; AFreeImageOnUpdate: Boolean = True);
|
||||
AData: Pointer = nil; AForceUpdate: Boolean = False;
|
||||
AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True);
|
||||
procedure DrawFormBackground(var AImage: TLazIntfImage; var ACanvas: TLazCanvas);
|
||||
procedure RenderChildWinControls(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; ACDControlsList: TFPList);
|
||||
@ -219,7 +220,8 @@ end;
|
||||
// If AForceUpdate=True then it will update even if the width and height remain the same
|
||||
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
||||
AData: Pointer = nil; AForceUpdate: Boolean = False; AFreeImageOnUpdate: Boolean = True);
|
||||
AData: Pointer = nil; AForceUpdate: Boolean = False;
|
||||
AFreeImageOnUpdate: Boolean = True; ADataOwner: Boolean = True);
|
||||
var
|
||||
lRawImage: TRawImage;
|
||||
lPixelSize: Byte;
|
||||
@ -269,7 +271,7 @@ begin
|
||||
end;
|
||||
|
||||
AImage := TLazIntfImage.Create(AWidth, AHeight);
|
||||
AImage.SetRawImage(lRawImage);
|
||||
AImage.SetRawImage(lRawImage, ADataOwner);
|
||||
|
||||
if (ACanvas <> nil) then ACanvas.Free;
|
||||
ACanvas := TLazCanvas.Create(AImage);
|
||||
|
@ -2175,7 +2175,7 @@ function TCDWidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
|
||||
B: Boolean; }
|
||||
begin
|
||||
{$ifdef VerboseCDWinAPI}
|
||||
WriteLn('[WinAPI ExtTextOut]');
|
||||
DebugLn('[WinAPI ExtTextOut]');
|
||||
{$endif}
|
||||
|
||||
Result := False;
|
||||
|
@ -2186,7 +2186,6 @@ var
|
||||
lCanvas: TLazCanvas = nil;
|
||||
lWidth, lHeight: jint;
|
||||
lDestCanvas: TLazCanvas;
|
||||
lDestX, lDestY: Integer;
|
||||
begin
|
||||
{$ifdef VerboseCDText}
|
||||
DebugLn(Format(':>[WinAPI ExtTextOut] DC=%x javaEnvRef=%x Str=%s X=%d Y=%d',
|
||||
@ -2203,8 +2202,6 @@ begin
|
||||
if not IsValidDC(DC) then Exit;
|
||||
|
||||
lDestCanvas := TLazCanvas(DC);
|
||||
lDestX := X + lDestCanvas.BaseWindowOrg.X;
|
||||
lDestY := Y + lDestCanvas.BaseWindowOrg.Y;
|
||||
|
||||
if (javaEnvRef = nil) then Exit;
|
||||
|
||||
@ -2224,8 +2221,8 @@ begin
|
||||
lHeight := javaEnvRef^^.GetLongField(javaEnvRef, javaActivityObject, javaField_lclheight);
|
||||
|
||||
{$ifdef VerboseCDText}
|
||||
DebugLn(Format(':[WinAPI ExtTextOut] lDestX=%d lDestY=%d lWidth=%d lHeight=%d',
|
||||
[lDestX, lDestY, lWidth, lHeight]));
|
||||
DebugLn(Format(':[WinAPI ExtTextOut] lWidth=%d lHeight=%d',
|
||||
[lWidth, lHeight]));
|
||||
{$endif}
|
||||
|
||||
// ---------------------------
|
||||
@ -2236,20 +2233,17 @@ begin
|
||||
AndroidBitmap_lockPixels(javaEnvRef, lJavaBitmap, @pixels);
|
||||
|
||||
// Prepare the non-native image and canvas
|
||||
UpdateControlLazImageAndCanvas(lImage, lCanvas, lWidth, lHeight, clfRGBA32, pixels, True, False);
|
||||
UpdateControlLazImageAndCanvas(lImage, lCanvas, lWidth, lHeight, clfRGBA32, pixels, True, False, False);
|
||||
|
||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] Before CanvasCopyRect');{$endif}
|
||||
// Execute the copy
|
||||
lDestCanvas.CanvasCopyRect(lCanvas, lDestX, lDestY, 0, 0, lWidth, lHeight); // try also AlphaBlend
|
||||
lDestCanvas.AlphaBlend(lCanvas, X, Y, 0, 0, lWidth, lHeight);
|
||||
|
||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] After CanvasCopyRect');{$endif}
|
||||
// Release the bitmap lock
|
||||
AndroidBitmap_unlockPixels(javaEnvRef, lJavaBitmap);
|
||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] After AndroidBitmap_unlockPixels');{$endif}
|
||||
lCanvas.Free;
|
||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] B');{$endif}
|
||||
//lImage.Free;
|
||||
lImage.Free;
|
||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] C');{$endif}
|
||||
// Release the bitmap lock
|
||||
AndroidBitmap_unlockPixels(javaEnvRef, lJavaBitmap);
|
||||
|
||||
{$ifdef VerboseCDText}
|
||||
DebugLn(':<[WinAPI ExtTextOut]');
|
||||
|
@ -392,48 +392,57 @@ end;
|
||||
procedure TLazCanvas.AlphaBlend(ASource: TLazCanvas;
|
||||
const ADestX, ADestY, ASourceX, ASourceY, ASourceWidth, ASourceHeight: Integer);
|
||||
var
|
||||
x, y, CurX, CurY: Integer;
|
||||
x, y, CurDestX, CurDestY, CurSrcX, CurSrcY: Integer;
|
||||
MaskValue, InvMaskValue: Word;
|
||||
CurColor: TFPColor;
|
||||
CurColor, SrcColor: TFPColor;
|
||||
lDrawWidth, lDrawHeight: Integer;
|
||||
begin
|
||||
// Take care not to draw outside the destination area
|
||||
lDrawWidth := Min(Self.Width - ADestX, ASource.Width);
|
||||
lDrawHeight := Min(Self.Height - ADestY, ASource.Height);
|
||||
lDrawWidth := Min(Self.Width - ADestX, ASource.Width - ASourceX);
|
||||
lDrawHeight := Min(Self.Height - ADestY, ASource.Height - ASourceY);
|
||||
lDrawWidth := Min(lDrawWidth, ASourceWidth);
|
||||
lDrawHeight := Min(lDrawHeight, ASourceHeight);
|
||||
//DebugLn(Format('[TLazCanvas.AlphaBlend] lDrawWidth=%d lDrawHeight=%d',
|
||||
// [lDrawWidth, lDrawHeight]));
|
||||
for y := 0 to lDrawHeight - 1 do
|
||||
begin
|
||||
for x := 0 to lDrawWidth - 1 do
|
||||
begin
|
||||
CurX := ADestX + x;
|
||||
CurY := ADestY + y;
|
||||
CurDestX := ADestX + x;
|
||||
CurDestY := ADestY + y;
|
||||
CurSrcX := ASourceX + x;
|
||||
CurSrcY := ASourceY + y;
|
||||
|
||||
// Never draw outside the destination
|
||||
if (CurX < 0) or (CurY < 0) then Continue;
|
||||
if (CurDestX < 0) or (CurDestY < 0) then Continue;
|
||||
|
||||
MaskValue := ASource.Colors[x, y].alpha;
|
||||
MaskValue := ASource.Colors[CurSrcX, CurSrcY].alpha;
|
||||
InvMaskValue := $FFFF - MaskValue;
|
||||
|
||||
if MaskValue = $FFFF then
|
||||
begin
|
||||
Self.Colors[CurX, CurY] := ASource.Colors[x, y];
|
||||
Self.Colors[CurDestX, CurDestY] := ASource.Colors[CurSrcX, CurSrcY];
|
||||
end
|
||||
else if MaskValue > $00 then
|
||||
begin
|
||||
CurColor := Self.Colors[CurX, CurY];
|
||||
CurColor := Self.Colors[CurDestX, CurDestY];
|
||||
SrcColor := ASource.Colors[CurSrcX, CurSrcY];
|
||||
|
||||
CurColor.Red := Round(
|
||||
CurColor.Red * InvMaskValue / $FFFF +
|
||||
ASource.Colors[x, y].Red * MaskValue / $FFFF);
|
||||
SrcColor.Red * MaskValue / $FFFF);
|
||||
|
||||
CurColor.Green := Round(
|
||||
CurColor.Green * InvMaskValue / $FFFF +
|
||||
ASource.Colors[x, y].Green * MaskValue / $FFFF);
|
||||
SrcColor.Green * MaskValue / $FFFF);
|
||||
|
||||
CurColor.Blue := Round(
|
||||
CurColor.Blue * InvMaskValue / $FFFF +
|
||||
ASource.Colors[x, y].Blue * MaskValue / $FFFF);
|
||||
SrcColor.Blue * MaskValue / $FFFF);
|
||||
|
||||
Self.Colors[CurX, CurY] := CurColor;
|
||||
CurColor.alpha := alphaOpaque;
|
||||
|
||||
Self.Colors[CurDestX, CurDestY] := CurColor;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user