diff --git a/ReadMe.txt b/ReadMe.txt index a3c1ecf..c4394a1 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -54,6 +54,13 @@ NOT WORKING YET CHANGES +Version 1.7 (2019-08-XX) + +- Allow to take a screenshot of the fullscreen including the skin. +- Add the KML Icon if present in the navigation menu header (only support PNG or 32bits BMP in the ICO file). +- Allow an optional overlapping LCD part stuck to the screen when swiping the 2 calc parts. + + Version 1.6 (2019-07-15) - Add option to prevent the pinch zoom. @@ -159,7 +166,6 @@ The Eric's Real scripts ("real*.kml" and "real*.bmp/png") are embedded in this a TODO - Retain a key by right clicking if it is from a mouse. -- Allow screenshot of the fullscreen including the skin. - Add the name of the file in the toast "State saved". - Add the KML icon in the navigation menu header. - Add the possibility to load and save the flash in another file. diff --git a/app/src/main/cpp/android-layer.c b/app/src/main/cpp/android-layer.c index 1b8ce5c..f9c10ef 100644 --- a/app/src/main/cpp/android-layer.c +++ b/app/src/main/cpp/android-layer.c @@ -15,24 +15,6 @@ #include "core/pch.h" #include "emu.h" -// Serial.c -//BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort) { -// return 0; -//} -//VOID CommClose(VOID) { -//} -//VOID CommSetBaud(VOID) { -//} -//BOOL UpdateUSRQ(VOID) { -// return 0; -//} -//VOID CommTxBRK(VOID) { -//} -//VOID CommTransmit(VOID) { -//} -//VOID CommReceive(VOID) { -//} - // udp.c TCHAR szUdpServer[1024] = _T("localhost"); WORD wUdpPort = 5025; // scpi-raw diff --git a/app/src/main/cpp/emu-jni.c b/app/src/main/cpp/emu-jni.c index 14ae503..74c89cd 100644 --- a/app/src/main/cpp/emu-jni.c +++ b/app/src/main/cpp/emu-jni.c @@ -439,51 +439,63 @@ JNIEXPORT jboolean JNICALL Java_org_emulator_calculator_NativeLib_copyLCD(JNIEnv // INT nxSize, nySize; // GetSizeLcdBitmap(&nxSize,&nySize); // get LCD size - HDC hSrcDC = hLcdDC; // use display HDC as source - if(!hSrcDC) + + void *pixelsDestination; + if ((ret = AndroidBitmap_lockPixels(env, bitmapLCD, &pixelsDestination)) < 0) { + LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); return JNI_FALSE; + } + + if(hLcdDC && hLcdDC->selectedBitmap) { + HBITMAP hBitmapSource = hLcdDC->selectedBitmap; + void * pixelsSource = (void *) hBitmapSource->bitmapBits; + BOOL reverseHeight = hBitmapSource->bitmapInfoHeader->biHeight < 0; + + int sourceWidth = hBitmapSource->bitmapInfoHeader->biWidth; + int sourceHeight = abs(hBitmapSource->bitmapInfoHeader->biHeight); // Can be < 0 + + UINT sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; + int sourceStride = 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); + + HPALETTE palette = hLcdDC->realizedPalette; + if(!palette) + palette = hLcdDC->selectedPalette; + PALETTEENTRY * palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? + palette->paletteLog->palPalEntry : NULL; + if(!palPalEntry && sourceBitCount <= 8 && hBitmapSource->bitmapInfoHeader->biClrUsed > 0) + palPalEntry = (PALETTEENTRY *)hBitmapSource->bitmapInfo->bmiColors; + int destinationWidth = bitmapLCDInfo.width; + int destinationHeight = bitmapLCDInfo.height; + int destinationBitCount = 32; + int destinationStride = bitmapLCDInfo.stride; - HBITMAP hBmp = hSrcDC->selectedBitmap; - if (hBmp && hBmp->bitmapInfoHeader && hBmp->bitmapInfoHeader->biWidth == bitmapLCDInfo.width && - abs(hBmp->bitmapInfoHeader->biHeight) == bitmapLCDInfo.height) { - INT nxO = 0, nyO = 0; // origin in HDC - void *pixelsDestination; - if ((ret = AndroidBitmap_lockPixels(env, bitmapLCD, &pixelsDestination)) < 0) { - LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); - return JNI_FALSE; - } - - // if (nCurrentHardware == HDW_SACA) - // { - // TCHAR cBuffer[32]; // temp. buffer for text - // MSG msg; - // - // // calculate bitmap origins from hWindowDC - // nxO = nLcdX; if (nxO > 1) { nxO -= 2; nxSize += 4; }; - // nyO = nLcdY; if (nyO > 1) { nyO -= 2; nySize += 4; }; - // - // hSrcDC = hWindowDC; // use output HDC as source - // } EnterCriticalSection(&csGDILock); // solving NT GDI problems + UINT nLines = MAINSCREENHEIGHT; - // copy display area - //BitBlt(hBmpDC,0,0,nxSize,nySize,hSrcDC,nxO,nyO,SRCCOPY); + // copy header display area + StretchBltInternal(0, 0, 131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom, pixelsDestination, destinationBitCount, + destinationStride, destinationWidth, destinationHeight, + Chipset.d0offset, 0, 131, Chipset.d0size, pixelsSource, sourceBitCount, + sourceStride, sourceWidth, sourceHeight, + SRCCOPY, reverseHeight, palPalEntry, 0, 0); + + + // copy main display area + StretchBltInternal(0, Chipset.d0size*nLcdZoom*nGdiYZoom, 131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom, pixelsDestination, destinationBitCount, + destinationStride, destinationWidth, destinationHeight, + Chipset.boffset, Chipset.d0size, 131, nLines, pixelsSource, sourceBitCount, + sourceStride, sourceWidth, sourceHeight, + SRCCOPY, reverseHeight, palPalEntry, 0, 0); + // copy menu display area + StretchBltInternal(0, (nLines+Chipset.d0size)*nLcdZoom*nGdiYZoom, 131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom, pixelsDestination, destinationBitCount, + destinationStride, destinationWidth, destinationHeight, + 0, (nLines+Chipset.d0size), 131, MENUHEIGHT, pixelsSource, sourceBitCount, + sourceStride, sourceWidth, sourceHeight, + SRCCOPY, reverseHeight, palPalEntry, 0, 0); - size_t strideSource = ((unsigned int) (4 * ((hBmp->bitmapInfoHeader->biWidth * - hBmp->bitmapInfoHeader->biBitCount + 31) / - 32))); - size_t strideDestination = bitmapLCDInfo.stride; - VOID *bitmapBitsSource = (VOID *) hBmp->bitmapBits; - VOID *bitmapBitsDestination = pixelsDestination; - int biHeight = abs(hBmp->bitmapInfoHeader->biHeight); - for (int y = 0; y < biHeight; y++) { - memcpy(bitmapBitsDestination, bitmapBitsSource, strideSource); - bitmapBitsSource += strideSource; - bitmapBitsDestination += strideDestination; - } LeaveCriticalSection(&csGDILock); AndroidBitmap_unlockPixels(env, bitmapLCD); return JNI_TRUE; diff --git a/app/src/main/cpp/win32-layer.c b/app/src/main/cpp/win32-layer.c index 84f0959..ba295a1 100644 --- a/app/src/main/cpp/win32-layer.c +++ b/app/src/main/cpp/win32-layer.c @@ -1592,6 +1592,15 @@ BOOL GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT *lpwndpl) { } BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl) { return 0; } extern void draw(); + +void StretchBltInternal(int xDest, int yDest, int wDest, int hDest, const void *pixelsDestination, + int destinationBitCount, int destinationStride, int destinationWidth, + int destinationHeight, int xSrc, int ySrc, int hSrc, int wSrc, + const void *pixelsSource, UINT sourceBitCount, int sourceStride, + int sourceWidth, int sourceHeight, DWORD rop, BOOL reverseHeight, + const PALETTEENTRY *palPalEntry, COLORREF brushColor, + COLORREF backgroundColor); + BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase) { // Update when switch the screen off draw(); //TODO Need a true WM_PAINT event! @@ -1996,23 +2005,44 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc backgroundColor = hdcDest->backgroundColor; } - int dst_maxx = xDest + wDest; - int dst_maxy = yDest + hDest; + StretchBltInternal(xDest, yDest, wDest, hDest, pixelsDestination, destinationBitCount, + destinationStride, destinationWidth, destinationHeight, + xSrc, ySrc, wSrc, hSrc, pixelsSource, sourceBitCount, + sourceStride, sourceWidth, sourceHeight, + rop, reverseHeight, palPalEntry, brushColor, backgroundColor); - if(xDest < 0) { + if(jniEnv && hdcDest->hdcCompatible == NULL && (ret = AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen)) < 0) { + LOGD("AndroidBitmap_unlockPixels() failed ! error=%d", ret); + return FALSE; + } + + return TRUE; + } + return FALSE; +} + +void StretchBltInternal(int xDest, int yDest, int wDest, int hDest, + const void *pixelsDestination, int destinationBitCount, int destinationStride, int destinationWidth, int destinationHeight, + int xSrc, int ySrc, int wSrc, int hSrc, + const void *pixelsSource, UINT sourceBitCount, int sourceStride, int sourceWidth, int sourceHeight, + DWORD rop, BOOL reverseHeight, const PALETTEENTRY *palPalEntry, COLORREF brushColor, COLORREF backgroundColor) { + int dst_maxx = xDest + wDest; + int dst_maxy = yDest + hDest; + + if(xDest < 0) { wDest += xDest; xDest = 0; } - if(yDest < 0) { + if(yDest < 0) { hDest += yDest; yDest = 0; } - if(dst_maxx > destinationWidth) + if(dst_maxx > destinationWidth) dst_maxx = destinationWidth; - if(dst_maxy > destinationHeight) + if(dst_maxy > destinationHeight) dst_maxy = destinationHeight; - for (int y = yDest; y < dst_maxy; y++) { + for (int y = yDest; y < dst_maxy; y++) { int src_cury = ySrc + (y - yDest) * hSrc / hDest; if(!reverseHeight) src_cury = sourceHeight - 1 - src_cury; @@ -2154,16 +2184,8 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc } } } - - if(jniEnv && hdcDest->hdcCompatible == NULL && (ret = AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen)) < 0) { - LOGD("AndroidBitmap_unlockPixels() failed ! error=%d", ret); - return FALSE; - } - - return TRUE; - } - return FALSE; } + UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq) { if(prgbq && hdc && hdc->realizedPalette && hdc->realizedPalette->paletteLog && hdc->realizedPalette->paletteLog->palPalEntry diff --git a/app/src/main/cpp/win32-layer.h b/app/src/main/cpp/win32-layer.h index 370f9bd..6a9b557 100644 --- a/app/src/main/cpp/win32-layer.h +++ b/app/src/main/cpp/win32-layer.h @@ -720,6 +720,13 @@ extern BOOL BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, in #define HALFTONE 4 extern int SetStretchBltMode(HDC hdc, int mode); extern BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop); +extern void StretchBltInternal(int xDest, int yDest, int wDest, int hDest, const void *pixelsDestination, + int destinationBitCount, int destinationStride, int destinationWidth, + int destinationHeight, int xSrc, int ySrc, int hSrc, int wSrc, + const void *pixelsSource, UINT sourceBitCount, int sourceStride, + int sourceWidth, int sourceHeight, DWORD rop, BOOL reverseHeight, + const PALETTEENTRY *palPalEntry, COLORREF brushColor, + COLORREF backgroundColor); extern UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq); /* constants for CreateDIBitmap */ #define CBM_INIT 0x04L /* initialize bitmap */ diff --git a/app/src/main/java/org/emulator/calculator/LCDOverlappingView.java b/app/src/main/java/org/emulator/calculator/LCDOverlappingView.java index a8dfe51..3393e24 100644 --- a/app/src/main/java/org/emulator/calculator/LCDOverlappingView.java +++ b/app/src/main/java/org/emulator/calculator/LCDOverlappingView.java @@ -7,6 +7,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.util.Log; @@ -21,6 +22,8 @@ public class LCDOverlappingView extends View { private SharedPreferences sharedPreferences; private Paint paint = new Paint(); + private Rect srcBitmapCopy = new Rect(); + private Rect dstBitmapCopy = new Rect(); private Bitmap bitmapLCD; private float bitmapRatio = -1; private float minViewSize = 200.0f; @@ -35,8 +38,8 @@ public class LCDOverlappingView extends View { sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); - paint.setFilterBitmap(true); - paint.setAntiAlias(true); + //paint.setFilterBitmap(true); + //paint.setAntiAlias(true); DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); @@ -168,7 +171,7 @@ public class LCDOverlappingView extends View { protected void onDraw(Canvas canvas) { //if(debug) Log.d(TAG, "onDraw()"); - canvas.drawColor(Color.RED); + canvas.drawColor(Color.RED); //TODO to remove if(this.overlappingLCDMode > 0 && bitmapLCD != null) { canvas.save(); @@ -176,6 +179,11 @@ public class LCDOverlappingView extends View { canvas.scale((float) getWidth() / (float) bitmapLCD.getWidth(), (float) getHeight() / (float) bitmapLCD.getHeight()); canvas.drawBitmap(bitmapLCD, 0, 0, paint); canvas.restore(); +// int x = NativeLib.getScreenPositionX(); +// int y = NativeLib.getScreenPositionY(); +// srcBitmapCopy.set(x, y, x + NativeLib.getScreenWidth(), y + NativeLib.getScreenHeight()); +// dstBitmapCopy.set(0, 0, getWidth(), getHeight()); +// canvas.drawBitmap(mainScreenView.getBitmap(), srcBitmapCopy, dstBitmapCopy, paint); } } @@ -186,8 +194,10 @@ public class LCDOverlappingView extends View { case NativeLib.CALLBACK_TYPE_INVALIDATE: //if(debug) Log.d(TAG, "PAINT updateCallback() postInvalidate()"); if(debug) Log.d(TAG, "updateCallback() CALLBACK_TYPE_INVALIDATE"); - NativeLib.copyLCD(bitmapLCD); - postInvalidate(); + if(bitmapLCD.getWidth() > 1) { + NativeLib.copyLCD(bitmapLCD); + postInvalidate(); + } break; case NativeLib.CALLBACK_TYPE_WINDOW_RESIZE: // New Bitmap size diff --git a/app/src/main/java/org/emulator/calculator/MainScreenView.java b/app/src/main/java/org/emulator/calculator/MainScreenView.java index 4491c54..090cd7a 100644 --- a/app/src/main/java/org/emulator/calculator/MainScreenView.java +++ b/app/src/main/java/org/emulator/calculator/MainScreenView.java @@ -387,4 +387,8 @@ public class MainScreenView extends PanAndScaleView { } return 0; } + + public Bitmap getBitmap() { + return bitmapMainScreen; + } } diff --git a/app/src/main/java/org/emulator/forty/eight/MainActivity.java b/app/src/main/java/org/emulator/forty/eight/MainActivity.java index 2f44482..3a52a11 100644 --- a/app/src/main/java/org/emulator/forty/eight/MainActivity.java +++ b/app/src/main/java/org/emulator/forty/eight/MainActivity.java @@ -349,6 +349,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On OnObjectLoad(); } else if (id == R.id.nav_save_object) { OnObjectSave(); + } else if (id == R.id.nav_copy_fullscreen) { + OnViewCopyFullscreen(); } else if (id == R.id.nav_copy_screen) { OnViewCopy(); } else if (id == R.id.nav_copy_stack) { @@ -749,6 +751,30 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.filename) + "-object.hp"); startActivityForResult(intent, INTENT_OBJECT_SAVE); } + private void OnViewCopyFullscreen() { + Bitmap bitmapScreen = mainScreenView.getBitmap(); + if(bitmapScreen == null) + return; + String imageFilename = getString(R.string.filename) + "-" + new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US).format(new Date()); + try { + File storagePath = new File(this.getExternalCacheDir(), ""); + File imageFile = File.createTempFile(imageFilename, ".png", storagePath); + FileOutputStream fileOutputStream = new FileOutputStream(imageFile); + bitmapScreen.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream); + fileOutputStream.close(); + String mimeType = "application/png"; + Intent intent = new Intent(android.content.Intent.ACTION_SEND); + intent.setType(mimeType); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intent.EXTRA_SUBJECT, R.string.message_screenshot); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this,this.getPackageName() + ".provider", imageFile)); + startActivity(Intent.createChooser(intent, getString(R.string.message_share_screenshot))); + } catch (Exception e) { + e.printStackTrace(); + showAlert(e.getMessage()); + } + } private void OnViewCopy() { int width = NativeLib.getScreenWidth(); int height = NativeLib.getScreenHeight(); diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml index f3a1d44..f09a8ea 100644 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ b/app/src/main/res/menu/activity_main_drawer.xml @@ -52,6 +52,10 @@ android:id="@+id/nav_save_object" android:icon="@drawable/ic_save_alt_black_24dp" android:title="@string/nav_save_object" /> + Load Object... Save Object... Copy Screen + Copy Fullscreen Copy Stack Recent Edit