mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-05 05:58:31 +02:00
customdrawn-android: Implements DebugLn/DebugOut and advances the painting code, painting already works inside Pascal, but not yet when using TLazCanvas
git-svn-id: trunk@33819 -
This commit is contained in:
parent
fb4a6b3045
commit
fa4d4ca971
@ -149,6 +149,13 @@ type
|
||||
|
||||
function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
|
||||
{$endif}
|
||||
{$ifdef CD_Android}
|
||||
procedure AndroidDebugLn(AStr: string);
|
||||
{$endif}
|
||||
// For unusual implementations of DebugLn/DebugOut
|
||||
public
|
||||
AccumulatedStr: string;
|
||||
procedure AccumulatingDebugOut(AStr: string);
|
||||
protected
|
||||
{function CreateThemeServices: TThemeServices; override;}
|
||||
{function GetAppHandle: THandle; override;
|
||||
@ -203,9 +210,9 @@ function WindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
|
||||
{$endif}
|
||||
|
||||
{$ifndef CD_Android_NATIVEAPP}
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_stringFromJNI(env:PJNIEnv;this:jobject):jstring; cdecl;
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_intFromJNI(env:PJNIEnv;this:jobject): jint; cdecl;
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_LCLDrawToBitmap(
|
||||
function Java_com_pascal_lclproject_LCLActivity_stringFromJNI(env:PJNIEnv;this:jobject):jstring; cdecl;
|
||||
function Java_com_pascal_lclproject_LCLActivity_intFromJNI(env:PJNIEnv;this:jobject): jint; cdecl;
|
||||
function Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap(
|
||||
env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
|
||||
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
|
||||
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl;
|
||||
|
@ -29,6 +29,10 @@ begin
|
||||
CDWidgetSet := Self;
|
||||
FTerminating := False;
|
||||
|
||||
// Setup DebugLn
|
||||
DebugLnProc := @AndroidDebugLn;
|
||||
DebugOutProc := @AccumulatingDebugOut;
|
||||
|
||||
BackendCreate;
|
||||
end;
|
||||
|
||||
|
@ -395,7 +395,7 @@ end;
|
||||
const curClass:JClass=nil;
|
||||
nativeCodeLoaded:JfieldID=nil;
|
||||
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_stringFromJNI(env:PJNIEnv;this:jobject):jstring; cdecl;
|
||||
function Java_com_pascal_lclproject_LCLActivity_stringFromJNI(env:PJNIEnv;this:jobject):jstring; cdecl;
|
||||
var x:single;
|
||||
begin
|
||||
{ __android_log_write(ANDROID_LOG_INFO,'nativetest','Java_com_bero_nativetest_Main_stringFromJNI entered');
|
||||
@ -405,37 +405,85 @@ begin
|
||||
__android_log_write(ANDROID_LOG_INFO,'nativetest','Java_com_bero_nativetest_Main_stringFromJNI exited');}
|
||||
end;
|
||||
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_intFromJNI(env:PJNIEnv;this:jobject): jint; cdecl;
|
||||
function Java_com_pascal_lclproject_LCLActivity_intFromJNI(env:PJNIEnv;this:jobject): jint; cdecl;
|
||||
begin
|
||||
Result := 8;
|
||||
end;
|
||||
|
||||
function Java_com_pascal_jnitest_AndroidJNITest_LCLDrawToBitmap(
|
||||
function Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap(
|
||||
env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
|
||||
var
|
||||
pixels: PCardinal;
|
||||
lCurForm: TCDNonNativeForm;
|
||||
|
||||
struct : TPaintStruct;
|
||||
lWidth, lHeight: Integer;
|
||||
lBitmap, lMask: HBITMAP;
|
||||
lRawImage: TRawImage;
|
||||
{$IFDEF VerboseCDPaintProfiler}
|
||||
lTimeStart: TDateTime;
|
||||
{$ENDIF}
|
||||
begin
|
||||
Result := 0;
|
||||
AndroidBitmap_lockPixels(env, abitmap, @pixels);
|
||||
|
||||
// debug info to check if we are painting
|
||||
pixels[30*width+30] := $FFFFFFFF;
|
||||
pixels[30*width+31] := $FFFFFFFF;
|
||||
pixels[30*width+32] := $FFFFFFFF;
|
||||
pixels[30*width+33] := $FFFFFFFF;
|
||||
pixels[30*width+34] := $FFFFFFFF;
|
||||
pixels[30*width+35] := $FFFFFFFF;
|
||||
|
||||
lCurForm := GetCurrentForm();
|
||||
if lCurForm <> nil then
|
||||
begin
|
||||
{$IFDEF VerboseCDPaintProfiler}
|
||||
//lTimeStart := NowUTC();
|
||||
{$ENDIF}
|
||||
{$IFDEF VerboseCDWindow}
|
||||
//DebugLn(Format('[TCDWSCustomForm.EvPaint] AWindowInfo: %x', [PtrInt(AWindowInfo)]));
|
||||
{$ENDIF}
|
||||
//if (AWinControl = nil) or (AWindowInfo = nil) then Exit;
|
||||
|
||||
lWidth := 200;//Round(AWinControl.width);
|
||||
lHeight := 200;//Round(AWinControl.height);
|
||||
|
||||
FillChar(struct, SizeOf(TPaintStruct), 0);
|
||||
|
||||
// Prepare the non-native image and canvas
|
||||
UpdateControlLazImageAndCanvas(lCurForm.Image, lCurForm.Canvas, lWidth, lHeight, clfBGRA32, pixels);
|
||||
|
||||
struct.hdc := HDC(lCurForm.Canvas);
|
||||
|
||||
// Send the paint message to the LCL
|
||||
{$IFDEF VerboseCDWindow}
|
||||
//DebugLn(Format('[TCDWSCustomForm.EvPaint] OnPaint event started context: %x', [struct.hdc]));
|
||||
{$ENDIF}
|
||||
LCLSendPaintMsg(lCurForm.LCLForm, struct.hdc, @struct);
|
||||
{$IFDEF VerboseCDWindow}
|
||||
//DebugLn('[TCDWSCustomForm.EvPaint] OnPaint event ended');
|
||||
{$ENDIF}
|
||||
|
||||
// Now paint all child win controls
|
||||
//RenderChildWinControls(AWindowInfo.Image, AWindowInfo.Canvas,
|
||||
//BackendGetCDWinControlList(TCustomForm(AWinControl)));
|
||||
end;
|
||||
|
||||
// Now returns the bitmap buffer to LCLActivity so that it can render it
|
||||
AndroidBitmap_unlockPixels(env, abitmap);
|
||||
end;
|
||||
|
||||
const NativeMethods: array[0..2] of JNINativeMethod=
|
||||
((name:'stringFromJNI';
|
||||
signature:'()Ljava/lang/String;';
|
||||
fnPtr:@Java_com_pascal_jnitest_AndroidJNITest_stringFromJNI;),
|
||||
fnPtr:@Java_com_pascal_lclproject_LCLActivity_stringFromJNI;),
|
||||
(name:'intFromJNI';
|
||||
signature:'()I';
|
||||
fnPtr:@Java_com_pascal_jnitest_AndroidJNITest_intFromJNI;),
|
||||
fnPtr:@Java_com_pascal_lclproject_LCLActivity_intFromJNI;),
|
||||
(name:'LCLDrawToBitmap';
|
||||
signature:'(IILandroid/graphics/Bitmap;)I';
|
||||
fnPtr:@Java_com_pascal_jnitest_AndroidJNITest_LCLDrawToBitmap;)
|
||||
fnPtr:@Java_com_pascal_lclproject_LCLActivity_LCLDrawToBitmap;)
|
||||
);
|
||||
|
||||
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
|
||||
@ -449,7 +497,7 @@ begin
|
||||
__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^=%x', [PtrInt(CurVM^)])));
|
||||
__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^^.reserved0=%x', [PtrInt(CurVM^^.reserved0)])));
|
||||
__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^^.GetEnv=%x', [PtrInt(Pointer(@CurVM^^.GetEnv))])));
|
||||
if curVM^^.GetEnv(curVM,@curEnv,JNI_VERSION_1_4)<>JNI_OK then begin //<<<--- THIS CRASHES
|
||||
{ if curVM^^.GetEnv(curVM,@curEnv,JNI_VERSION_1_4)<>JNI_OK then begin //<<<--- THIS CRASHES
|
||||
__android_log_write(ANDROID_LOG_INFO{FATAL},'nativetest','curVM^.GetEnv failed');
|
||||
// result:=JNI_ERR;
|
||||
// exit;
|
||||
@ -473,7 +521,7 @@ begin
|
||||
__android_log_write(ANDROID_LOG_FATAL,'nativetest','curEnv^.GetFieldID failed');
|
||||
result:=JNI_ERR;
|
||||
exit;
|
||||
end;
|
||||
end; }
|
||||
|
||||
result:=JNI_VERSION_1_4;// 1_6?
|
||||
end;
|
||||
@ -484,6 +532,17 @@ end;
|
||||
|
||||
{$endif}
|
||||
|
||||
procedure TCDWidgetSet.AndroidDebugLn(AStr: string);
|
||||
begin
|
||||
__android_log_write(ANDROID_LOG_INFO, 'lclproject', PChar(AccumulatedStr+AStr));
|
||||
AccumulatedStr := '';
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.AccumulatingDebugOut(AStr: string);
|
||||
begin
|
||||
AccumulatedStr := AccumulatedStr + AStr;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Method: TCDWidgetSet.Create
|
||||
Params: None
|
||||
@ -517,9 +576,9 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TCDWidgetSet.AppInit(var ScreenInfo: TScreenInfo);
|
||||
begin
|
||||
{$ifdef VerboseCDApplication}
|
||||
//DebugLn('TCDWidgetSet.AppInit');
|
||||
{$endif}
|
||||
{$ifdef VerboseCDApplication}
|
||||
DebugLn('TCDWidgetSet.AppInit');
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop);
|
||||
|
@ -26,24 +26,109 @@ type
|
||||
//CDControl: TCDControl;
|
||||
end;
|
||||
|
||||
TCDNonNativeForm = class
|
||||
public
|
||||
LCLForm: TCustomForm;
|
||||
Children: TFPList; // of TCDWinControl;
|
||||
// painting objects
|
||||
Image: TLazIntfImage;
|
||||
Canvas: TLazCanvas;
|
||||
end;
|
||||
|
||||
// Routines for non-native form
|
||||
|
||||
procedure InitNonNativeForms();
|
||||
function GetCurrentForm(): TCDNonNativeForm;
|
||||
function AddNewForm(AForm: TCustomForm): TCDNonNativeForm;
|
||||
procedure ShowForm(ACDForm: TCDNonNativeForm);
|
||||
procedure HideForm(ACDForm: TCDNonNativeForm);
|
||||
|
||||
// Routines for non-native wincontrol
|
||||
|
||||
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat);
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
||||
AData: Pointer = nil);
|
||||
procedure RenderChildWinControls(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; ACDControlsList: TFPList);
|
||||
//procedure RenderWinControl(var AImage: TLazIntfImage;
|
||||
// var ACanvas: TLazCanvas; ACDControlsList: TFPList);
|
||||
function FindControlWhichReceivedEvent(AForm: TCustomForm;
|
||||
AControlsList: TFPList; AX, AY: Integer): TWinControl;
|
||||
|
||||
// Other routines
|
||||
|
||||
function DateTimeToMilliseconds(aDateTime: TDateTime): Int64;
|
||||
function IsValidDC(ADC: HDC): Boolean;
|
||||
function IsValidGDIObject(AGDIObj: HGDIOBJ): Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
// List with the Z-order of non-native forms, index=0 is the bottom-most form
|
||||
var
|
||||
NonNativeForms: TFPList = nil;
|
||||
|
||||
procedure InitNonNativeForms();
|
||||
begin
|
||||
if NonNativeForms <> nil then Exit;
|
||||
NonNativeForms := TFPList.Create;
|
||||
end;
|
||||
|
||||
function GetCurrentForm(): TCDNonNativeForm;
|
||||
var
|
||||
lCount: Integer;
|
||||
begin
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn('GetCurrentForm');
|
||||
{$ENDIF}
|
||||
InitNonNativeForms();
|
||||
lCount := NonNativeForms.Count;
|
||||
if lCount = 0 then Result := nil
|
||||
else Result := TCDNonNativeForm(NonNativeForms.Items[lCount-1]);
|
||||
end;
|
||||
|
||||
function AddNewForm(AForm: TCustomForm): TCDNonNativeForm;
|
||||
var
|
||||
lFormInfo: TCDNonNativeForm;
|
||||
begin
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn('AddNewForm');
|
||||
{$ENDIF}
|
||||
InitNonNativeForms();
|
||||
lFormInfo := TCDNonNativeForm.Create;
|
||||
lFormInfo.LCLForm := AForm;
|
||||
lFormInfo.Children := TFPList.Create;
|
||||
NonNativeForms.Insert(0, lFormInfo);
|
||||
end;
|
||||
|
||||
procedure ShowForm(ACDForm: TCDNonNativeForm);
|
||||
var
|
||||
lCount, lCurIndex: Integer;
|
||||
begin
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn('ShowForm');
|
||||
{$ENDIF}
|
||||
InitNonNativeForms();
|
||||
lCount := NonNativeForms.Count;
|
||||
lCurIndex := NonNativeForms.IndexOf(ACDForm);
|
||||
NonNativeForms.Move(lCurIndex, lCount-1);
|
||||
end;
|
||||
|
||||
procedure HideForm(ACDForm: TCDNonNativeForm);
|
||||
var
|
||||
lCount, lCurIndex: Integer;
|
||||
begin
|
||||
InitNonNativeForms();
|
||||
lCount := NonNativeForms.Count;
|
||||
lCurIndex := NonNativeForms.IndexOf(ACDForm);
|
||||
NonNativeForms.Move(lCurIndex, 0);
|
||||
end;
|
||||
|
||||
procedure UpdateControlLazImageAndCanvas(var AImage: TLazIntfImage;
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat);
|
||||
var ACanvas: TLazCanvas; AWidth, AHeight: Integer; AFormat: TUpdateLazImageFormat;
|
||||
AData: Pointer = nil);
|
||||
var
|
||||
lRawImage: TRawImage;
|
||||
lPixelSize: Byte;
|
||||
begin
|
||||
{$IFDEF VerboseWinAPI}
|
||||
DebugLn(Format(':>[UpdateControlLazImageAndCanvas] Input Image: %x Canvas: %x',
|
||||
@ -62,7 +147,22 @@ begin
|
||||
clfBGR24: lRawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(AWidth, AHeight);
|
||||
clfBGRA32: lRawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(AWidth, AHeight);
|
||||
end;
|
||||
lRawImage.CreateData(True);
|
||||
|
||||
// Now connect the pixel buffer or create one
|
||||
if AData = nil then lRawImage.CreateData(True)
|
||||
else
|
||||
begin
|
||||
case AFormat of
|
||||
clfRGB16_R5G6B5: lPixelSize := 2;
|
||||
clfRGB24: lPixelSize := 3;
|
||||
clfRGB24UpsideDown: lPixelSize := 3;
|
||||
clfBGR24: lPixelSize := 3;
|
||||
clfBGRA32: lPixelSize := 4;
|
||||
end;
|
||||
|
||||
lRawImage.Data := AData;
|
||||
lRawImage.DataSize := AWidth * lPixelSize * AHeight;
|
||||
end;
|
||||
|
||||
AImage := TLazIntfImage.Create(AWidth, AHeight);
|
||||
AImage.SetRawImage(lRawImage);
|
||||
|
@ -33,16 +33,17 @@ var
|
||||
lWindowInfo: TAndroidWindowInfo;
|
||||
AForm: TCustomForm absolute AWinControl;
|
||||
begin
|
||||
{$ifdef VerboseCDWindow}
|
||||
(* {$ifdef VerboseCDWindow}
|
||||
DebugLn(Format(':>[TCDWSCustomForm.CreateHandle] AWinControl=%x Name=%s: %s',
|
||||
[PtrInt(AWinControl), AWinControl.Name, AWinControl.ClassName]));
|
||||
{$endif}
|
||||
{$endif}*)
|
||||
|
||||
Result := TLCLIntfhandle(AddNewForm(TCustomForm(AWinControl)));
|
||||
|
||||
{$ifdef VerboseCDWindow}
|
||||
(* {$ifdef VerboseCDWindow}
|
||||
DebugLn(Format(':<[TCDWSCustomForm.CreateHandle] Result=%x',
|
||||
[Result]));
|
||||
{$endif}
|
||||
{$endif}*)
|
||||
end;
|
||||
|
||||
class procedure TCDWSCustomForm.DestroyHandle(const AWinControl: TWinControl);
|
||||
@ -90,16 +91,18 @@ begin
|
||||
|
||||
if AWinControl.Visible then
|
||||
begin
|
||||
{$ifdef VerboseCDWindow}
|
||||
ShowForm(TCDNonNativeForm(AWinControl.Handle));
|
||||
(* {$ifdef VerboseCDWindow}
|
||||
DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=True AWinControl=%x Handle=%x',
|
||||
[PtrInt(AWinControl), PtrInt(AWinControl.Handle)]));
|
||||
{$endif}
|
||||
{$endif}*)
|
||||
end
|
||||
else
|
||||
begin
|
||||
{$ifdef VerboseCDWindow}
|
||||
HideForm(TCDNonNativeForm(AWinControl.Handle));
|
||||
(* {$ifdef VerboseCDWindow}
|
||||
DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=False AWinControl=%x', [PtrInt(AWinControl)]));
|
||||
{$endif}
|
||||
{$endif}*)
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user