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:
sekelsenmat 2011-11-28 10:17:58 +00:00
parent fb4a6b3045
commit fa4d4ca971
5 changed files with 198 additions and 25 deletions

View File

@ -149,6 +149,13 @@ type
function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl; function FindWindowByXID(XWindowID: X.TWindow; out AWindowInfo: TX11WindowInfo): TWinControl;
{$endif} {$endif}
{$ifdef CD_Android}
procedure AndroidDebugLn(AStr: string);
{$endif}
// For unusual implementations of DebugLn/DebugOut
public
AccumulatedStr: string;
procedure AccumulatingDebugOut(AStr: string);
protected protected
{function CreateThemeServices: TThemeServices; override;} {function CreateThemeServices: TThemeServices; override;}
{function GetAppHandle: THandle; override; {function GetAppHandle: THandle; override;
@ -203,9 +210,9 @@ function WindowProc(Window: HWnd; Msg: UInt; WParam: Windows.WParam;
{$endif} {$endif}
{$ifndef CD_Android_NATIVEAPP} {$ifndef CD_Android_NATIVEAPP}
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;
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;
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; env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl; function JNI_OnLoad(vm:PJavaVM;reserved:pointer):jint; cdecl;
procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl; procedure JNI_OnUnload(vm:PJavaVM;reserved:pointer); cdecl;

View File

@ -29,6 +29,10 @@ begin
CDWidgetSet := Self; CDWidgetSet := Self;
FTerminating := False; FTerminating := False;
// Setup DebugLn
DebugLnProc := @AndroidDebugLn;
DebugOutProc := @AccumulatingDebugOut;
BackendCreate; BackendCreate;
end; end;

View File

@ -395,7 +395,7 @@ end;
const curClass:JClass=nil; const curClass:JClass=nil;
nativeCodeLoaded:JfieldID=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; var x:single;
begin begin
{ __android_log_write(ANDROID_LOG_INFO,'nativetest','Java_com_bero_nativetest_Main_stringFromJNI entered'); { __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');} __android_log_write(ANDROID_LOG_INFO,'nativetest','Java_com_bero_nativetest_Main_stringFromJNI exited');}
end; 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 begin
Result := 8; Result := 8;
end; 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; env:PJNIEnv;this:jobject; width, height: jint; abitmap: jobject): jint; cdecl;
var var
pixels: PCardinal; pixels: PCardinal;
lCurForm: TCDNonNativeForm;
struct : TPaintStruct;
lWidth, lHeight: Integer;
lBitmap, lMask: HBITMAP;
lRawImage: TRawImage;
{$IFDEF VerboseCDPaintProfiler}
lTimeStart: TDateTime;
{$ENDIF}
begin begin
Result := 0; Result := 0;
AndroidBitmap_lockPixels(env, abitmap, @pixels); AndroidBitmap_lockPixels(env, abitmap, @pixels);
// debug info to check if we are painting
pixels[30*width+30] := $FFFFFFFF; pixels[30*width+30] := $FFFFFFFF;
pixels[30*width+31] := $FFFFFFFF; pixels[30*width+31] := $FFFFFFFF;
pixels[30*width+32] := $FFFFFFFF; pixels[30*width+32] := $FFFFFFFF;
pixels[30*width+33] := $FFFFFFFF; pixels[30*width+33] := $FFFFFFFF;
pixels[30*width+34] := $FFFFFFFF; pixels[30*width+34] := $FFFFFFFF;
pixels[30*width+35] := $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); AndroidBitmap_unlockPixels(env, abitmap);
end; end;
const NativeMethods: array[0..2] of JNINativeMethod= const NativeMethods: array[0..2] of JNINativeMethod=
((name:'stringFromJNI'; ((name:'stringFromJNI';
signature:'()Ljava/lang/String;'; signature:'()Ljava/lang/String;';
fnPtr:@Java_com_pascal_jnitest_AndroidJNITest_stringFromJNI;), fnPtr:@Java_com_pascal_lclproject_LCLActivity_stringFromJNI;),
(name:'intFromJNI'; (name:'intFromJNI';
signature:'()I'; signature:'()I';
fnPtr:@Java_com_pascal_jnitest_AndroidJNITest_intFromJNI;), fnPtr:@Java_com_pascal_lclproject_LCLActivity_intFromJNI;),
(name:'LCLDrawToBitmap'; (name:'LCLDrawToBitmap';
signature:'(IILandroid/graphics/Bitmap;)I'; 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; 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^=%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^^.reserved0=%x', [PtrInt(CurVM^^.reserved0)])));
__android_log_write(ANDROID_LOG_INFO,'nativetest',PChar(Format('CurVM^^.GetEnv=%x', [PtrInt(Pointer(@CurVM^^.GetEnv))]))); __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'); __android_log_write(ANDROID_LOG_INFO{FATAL},'nativetest','curVM^.GetEnv failed');
// result:=JNI_ERR; // result:=JNI_ERR;
// exit; // exit;
@ -473,7 +521,7 @@ begin
__android_log_write(ANDROID_LOG_FATAL,'nativetest','curEnv^.GetFieldID failed'); __android_log_write(ANDROID_LOG_FATAL,'nativetest','curEnv^.GetFieldID failed');
result:=JNI_ERR; result:=JNI_ERR;
exit; exit;
end; end; }
result:=JNI_VERSION_1_4;// 1_6? result:=JNI_VERSION_1_4;// 1_6?
end; end;
@ -484,6 +532,17 @@ end;
{$endif} {$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 Method: TCDWidgetSet.Create
Params: None Params: None
@ -517,9 +576,9 @@ end;
------------------------------------------------------------------------------} ------------------------------------------------------------------------------}
procedure TCDWidgetSet.AppInit(var ScreenInfo: TScreenInfo); procedure TCDWidgetSet.AppInit(var ScreenInfo: TScreenInfo);
begin begin
{$ifdef VerboseCDApplication} {$ifdef VerboseCDApplication}
//DebugLn('TCDWidgetSet.AppInit'); DebugLn('TCDWidgetSet.AppInit');
{$endif} {$endif}
end; end;
procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop); procedure TCDWidgetSet.AppRun(const ALoop: TApplicationMainLoop);

View File

@ -26,24 +26,109 @@ type
//CDControl: TCDControl; //CDControl: TCDControl;
end; 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; 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; procedure RenderChildWinControls(var AImage: TLazIntfImage;
var ACanvas: TLazCanvas; ACDControlsList: TFPList); var ACanvas: TLazCanvas; ACDControlsList: TFPList);
//procedure RenderWinControl(var AImage: TLazIntfImage; //procedure RenderWinControl(var AImage: TLazIntfImage;
// var ACanvas: TLazCanvas; ACDControlsList: TFPList); // var ACanvas: TLazCanvas; ACDControlsList: TFPList);
function FindControlWhichReceivedEvent(AForm: TCustomForm; function FindControlWhichReceivedEvent(AForm: TCustomForm;
AControlsList: TFPList; AX, AY: Integer): TWinControl; AControlsList: TFPList; AX, AY: Integer): TWinControl;
// Other routines
function DateTimeToMilliseconds(aDateTime: TDateTime): Int64; function DateTimeToMilliseconds(aDateTime: TDateTime): Int64;
function IsValidDC(ADC: HDC): Boolean; function IsValidDC(ADC: HDC): Boolean;
function IsValidGDIObject(AGDIObj: HGDIOBJ): Boolean; function IsValidGDIObject(AGDIObj: HGDIOBJ): Boolean;
implementation 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; 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 var
lRawImage: TRawImage; lRawImage: TRawImage;
lPixelSize: Byte;
begin begin
{$IFDEF VerboseWinAPI} {$IFDEF VerboseWinAPI}
DebugLn(Format(':>[UpdateControlLazImageAndCanvas] Input Image: %x Canvas: %x', DebugLn(Format(':>[UpdateControlLazImageAndCanvas] Input Image: %x Canvas: %x',
@ -62,7 +147,22 @@ begin
clfBGR24: lRawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(AWidth, AHeight); clfBGR24: lRawImage.Description.Init_BPP24_B8G8R8_BIO_TTB(AWidth, AHeight);
clfBGRA32: lRawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(AWidth, AHeight); clfBGRA32: lRawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(AWidth, AHeight);
end; 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 := TLazIntfImage.Create(AWidth, AHeight);
AImage.SetRawImage(lRawImage); AImage.SetRawImage(lRawImage);

View File

@ -33,16 +33,17 @@ var
lWindowInfo: TAndroidWindowInfo; lWindowInfo: TAndroidWindowInfo;
AForm: TCustomForm absolute AWinControl; AForm: TCustomForm absolute AWinControl;
begin begin
{$ifdef VerboseCDWindow} (* {$ifdef VerboseCDWindow}
DebugLn(Format(':>[TCDWSCustomForm.CreateHandle] AWinControl=%x Name=%s: %s', DebugLn(Format(':>[TCDWSCustomForm.CreateHandle] AWinControl=%x Name=%s: %s',
[PtrInt(AWinControl), AWinControl.Name, AWinControl.ClassName])); [PtrInt(AWinControl), AWinControl.Name, AWinControl.ClassName]));
{$endif} {$endif}*)
Result := TLCLIntfhandle(AddNewForm(TCustomForm(AWinControl)));
{$ifdef VerboseCDWindow} (* {$ifdef VerboseCDWindow}
DebugLn(Format(':<[TCDWSCustomForm.CreateHandle] Result=%x', DebugLn(Format(':<[TCDWSCustomForm.CreateHandle] Result=%x',
[Result])); [Result]));
{$endif} {$endif}*)
end; end;
class procedure TCDWSCustomForm.DestroyHandle(const AWinControl: TWinControl); class procedure TCDWSCustomForm.DestroyHandle(const AWinControl: TWinControl);
@ -90,16 +91,18 @@ begin
if AWinControl.Visible then if AWinControl.Visible then
begin begin
{$ifdef VerboseCDWindow} ShowForm(TCDNonNativeForm(AWinControl.Handle));
(* {$ifdef VerboseCDWindow}
DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=True AWinControl=%x Handle=%x', DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=True AWinControl=%x Handle=%x',
[PtrInt(AWinControl), PtrInt(AWinControl.Handle)])); [PtrInt(AWinControl), PtrInt(AWinControl.Handle)]));
{$endif} {$endif}*)
end end
else else
begin begin
{$ifdef VerboseCDWindow} HideForm(TCDNonNativeForm(AWinControl.Handle));
(* {$ifdef VerboseCDWindow}
DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=False AWinControl=%x', [PtrInt(AWinControl)])); DebugLn(Format('[TCDWSCustomForm.ShowHide] Visible=False AWinControl=%x', [PtrInt(AWinControl)]));
{$endif} {$endif}*)
end; end;
end; end;