mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-07 14:38:17 +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();
|
Paint localpaint = new Paint();
|
||||||
Rect localbounds = new Rect();
|
Rect localbounds = new Rect();
|
||||||
|
localpaint.setTextSize(18);
|
||||||
localpaint.getTextBounds(lcltext, 0, lcltext.length(), localbounds);
|
localpaint.getTextBounds(lcltext, 0, lcltext.length(), localbounds);
|
||||||
lclwidth = localbounds.width();
|
lclwidth = localbounds.width();
|
||||||
lclheight = localbounds.height();
|
lclheight = localbounds.height();
|
||||||
@ -93,7 +94,11 @@ public class LCLActivity extends Activity
|
|||||||
lclbitmap = Bitmap.createBitmap(lclwidth, lclheight, Bitmap.Config.ARGB_8888);
|
lclbitmap = Bitmap.createBitmap(lclwidth, lclheight, Bitmap.Config.ARGB_8888);
|
||||||
Canvas localcanvas = new Canvas(lclbitmap);
|
Canvas localcanvas = new Canvas(lclbitmap);
|
||||||
Paint localpaint = new Paint();
|
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
|
// LCLType definitions
|
||||||
@ -172,6 +177,7 @@ public class LCLActivity extends Activity
|
|||||||
public int lclbutton2;
|
public int lclbutton2;
|
||||||
public int lclbutton3;
|
public int lclbutton3;
|
||||||
public Bitmap lclbitmap;
|
public Bitmap lclbitmap;
|
||||||
|
public int lcltextsize;
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
|
@ -31,4 +31,8 @@
|
|||||||
{$endif}
|
{$endif}
|
||||||
{$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;
|
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
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 DrawFormBackground(var AImage: TLazIntfImage; var ACanvas: TLazCanvas);
|
||||||
procedure RenderChildWinControls(var AImage: TLazIntfImage;
|
procedure RenderChildWinControls(var AImage: TLazIntfImage;
|
||||||
var ACanvas: TLazCanvas; ACDControlsList: TFPList);
|
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
|
// If AForceUpdate=True then it will update even if the width and height remain the same
|
||||||
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
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
|
var
|
||||||
lRawImage: TRawImage;
|
lRawImage: TRawImage;
|
||||||
lPixelSize: Byte;
|
lPixelSize: Byte;
|
||||||
@ -269,7 +271,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
AImage := TLazIntfImage.Create(AWidth, AHeight);
|
AImage := TLazIntfImage.Create(AWidth, AHeight);
|
||||||
AImage.SetRawImage(lRawImage);
|
AImage.SetRawImage(lRawImage, ADataOwner);
|
||||||
|
|
||||||
if (ACanvas <> nil) then ACanvas.Free;
|
if (ACanvas <> nil) then ACanvas.Free;
|
||||||
ACanvas := TLazCanvas.Create(AImage);
|
ACanvas := TLazCanvas.Create(AImage);
|
||||||
|
@ -2175,7 +2175,7 @@ function TCDWidgetSet.ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
|
|||||||
B: Boolean; }
|
B: Boolean; }
|
||||||
begin
|
begin
|
||||||
{$ifdef VerboseCDWinAPI}
|
{$ifdef VerboseCDWinAPI}
|
||||||
WriteLn('[WinAPI ExtTextOut]');
|
DebugLn('[WinAPI ExtTextOut]');
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
Result := False;
|
Result := False;
|
||||||
|
@ -2186,7 +2186,6 @@ var
|
|||||||
lCanvas: TLazCanvas = nil;
|
lCanvas: TLazCanvas = nil;
|
||||||
lWidth, lHeight: jint;
|
lWidth, lHeight: jint;
|
||||||
lDestCanvas: TLazCanvas;
|
lDestCanvas: TLazCanvas;
|
||||||
lDestX, lDestY: Integer;
|
|
||||||
begin
|
begin
|
||||||
{$ifdef VerboseCDText}
|
{$ifdef VerboseCDText}
|
||||||
DebugLn(Format(':>[WinAPI ExtTextOut] DC=%x javaEnvRef=%x Str=%s X=%d Y=%d',
|
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;
|
if not IsValidDC(DC) then Exit;
|
||||||
|
|
||||||
lDestCanvas := TLazCanvas(DC);
|
lDestCanvas := TLazCanvas(DC);
|
||||||
lDestX := X + lDestCanvas.BaseWindowOrg.X;
|
|
||||||
lDestY := Y + lDestCanvas.BaseWindowOrg.Y;
|
|
||||||
|
|
||||||
if (javaEnvRef = nil) then Exit;
|
if (javaEnvRef = nil) then Exit;
|
||||||
|
|
||||||
@ -2224,8 +2221,8 @@ begin
|
|||||||
lHeight := javaEnvRef^^.GetLongField(javaEnvRef, javaActivityObject, javaField_lclheight);
|
lHeight := javaEnvRef^^.GetLongField(javaEnvRef, javaActivityObject, javaField_lclheight);
|
||||||
|
|
||||||
{$ifdef VerboseCDText}
|
{$ifdef VerboseCDText}
|
||||||
DebugLn(Format(':[WinAPI ExtTextOut] lDestX=%d lDestY=%d lWidth=%d lHeight=%d',
|
DebugLn(Format(':[WinAPI ExtTextOut] lWidth=%d lHeight=%d',
|
||||||
[lDestX, lDestY, lWidth, lHeight]));
|
[lWidth, lHeight]));
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@ -2236,20 +2233,17 @@ begin
|
|||||||
AndroidBitmap_lockPixels(javaEnvRef, lJavaBitmap, @pixels);
|
AndroidBitmap_lockPixels(javaEnvRef, lJavaBitmap, @pixels);
|
||||||
|
|
||||||
// Prepare the non-native image and canvas
|
// 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
|
// 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;
|
lCanvas.Free;
|
||||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] B');{$endif}
|
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] B');{$endif}
|
||||||
//lImage.Free;
|
lImage.Free;
|
||||||
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] C');{$endif}
|
{$ifdef VerboseCDText}DebugLn(':[WinAPI ExtTextOut] C');{$endif}
|
||||||
|
// Release the bitmap lock
|
||||||
|
AndroidBitmap_unlockPixels(javaEnvRef, lJavaBitmap);
|
||||||
|
|
||||||
{$ifdef VerboseCDText}
|
{$ifdef VerboseCDText}
|
||||||
DebugLn(':<[WinAPI ExtTextOut]');
|
DebugLn(':<[WinAPI ExtTextOut]');
|
||||||
|
@ -392,48 +392,57 @@ end;
|
|||||||
procedure TLazCanvas.AlphaBlend(ASource: TLazCanvas;
|
procedure TLazCanvas.AlphaBlend(ASource: TLazCanvas;
|
||||||
const ADestX, ADestY, ASourceX, ASourceY, ASourceWidth, ASourceHeight: Integer);
|
const ADestX, ADestY, ASourceX, ASourceY, ASourceWidth, ASourceHeight: Integer);
|
||||||
var
|
var
|
||||||
x, y, CurX, CurY: Integer;
|
x, y, CurDestX, CurDestY, CurSrcX, CurSrcY: Integer;
|
||||||
MaskValue, InvMaskValue: Word;
|
MaskValue, InvMaskValue: Word;
|
||||||
CurColor: TFPColor;
|
CurColor, SrcColor: TFPColor;
|
||||||
lDrawWidth, lDrawHeight: Integer;
|
lDrawWidth, lDrawHeight: Integer;
|
||||||
begin
|
begin
|
||||||
// Take care not to draw outside the destination area
|
// Take care not to draw outside the destination area
|
||||||
lDrawWidth := Min(Self.Width - ADestX, ASource.Width);
|
lDrawWidth := Min(Self.Width - ADestX, ASource.Width - ASourceX);
|
||||||
lDrawHeight := Min(Self.Height - ADestY, ASource.Height);
|
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
|
for y := 0 to lDrawHeight - 1 do
|
||||||
begin
|
begin
|
||||||
for x := 0 to lDrawWidth - 1 do
|
for x := 0 to lDrawWidth - 1 do
|
||||||
begin
|
begin
|
||||||
CurX := ADestX + x;
|
CurDestX := ADestX + x;
|
||||||
CurY := ADestY + y;
|
CurDestY := ADestY + y;
|
||||||
|
CurSrcX := ASourceX + x;
|
||||||
|
CurSrcY := ASourceY + y;
|
||||||
|
|
||||||
// Never draw outside the destination
|
// 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;
|
InvMaskValue := $FFFF - MaskValue;
|
||||||
|
|
||||||
if MaskValue = $FFFF then
|
if MaskValue = $FFFF then
|
||||||
begin
|
begin
|
||||||
Self.Colors[CurX, CurY] := ASource.Colors[x, y];
|
Self.Colors[CurDestX, CurDestY] := ASource.Colors[CurSrcX, CurSrcY];
|
||||||
end
|
end
|
||||||
else if MaskValue > $00 then
|
else if MaskValue > $00 then
|
||||||
begin
|
begin
|
||||||
CurColor := Self.Colors[CurX, CurY];
|
CurColor := Self.Colors[CurDestX, CurDestY];
|
||||||
|
SrcColor := ASource.Colors[CurSrcX, CurSrcY];
|
||||||
|
|
||||||
CurColor.Red := Round(
|
CurColor.Red := Round(
|
||||||
CurColor.Red * InvMaskValue / $FFFF +
|
CurColor.Red * InvMaskValue / $FFFF +
|
||||||
ASource.Colors[x, y].Red * MaskValue / $FFFF);
|
SrcColor.Red * MaskValue / $FFFF);
|
||||||
|
|
||||||
CurColor.Green := Round(
|
CurColor.Green := Round(
|
||||||
CurColor.Green * InvMaskValue / $FFFF +
|
CurColor.Green * InvMaskValue / $FFFF +
|
||||||
ASource.Colors[x, y].Green * MaskValue / $FFFF);
|
SrcColor.Green * MaskValue / $FFFF);
|
||||||
|
|
||||||
CurColor.Blue := Round(
|
CurColor.Blue := Round(
|
||||||
CurColor.Blue * InvMaskValue / $FFFF +
|
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;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user