mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 06:53:43 +00:00
Merge branch 'master' into mac
# Conflicts: # GpApp/Main.cpp
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#include "WindowDef.h"
|
||||
#include "WindowManager.h"
|
||||
|
||||
#include "PLApplication.h"
|
||||
#include "PLArrayView.h"
|
||||
#include "PLBigEndian.h"
|
||||
#include "PLButtonWidget.h"
|
||||
@@ -471,7 +472,7 @@ namespace PortabilityLayer
|
||||
Rect2i windowFullRect = WindowManager::GetInstance()->GetWindowFullRect(window);
|
||||
if (!windowFullRect.Contains(Vec2i(mouseEvent.m_x, mouseEvent.m_y)))
|
||||
{
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
SysBeep(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -834,7 +835,7 @@ namespace PortabilityLayer
|
||||
// If sound index is 0, play no sound
|
||||
|
||||
if (soundIndexes[0] != 0)
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
SysBeep(1);
|
||||
|
||||
const Rect dialogRect = alertResData.m_rect.ToRect();
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "WindowDef.h"
|
||||
#include "MacRomanConversion.h"
|
||||
|
||||
#include "PLApplication.h"
|
||||
#include "PLArrayView.h"
|
||||
#include "PLControlDefinitions.h"
|
||||
#include "PLCore.h"
|
||||
@@ -40,13 +41,15 @@ static const int kCancelButton = 2;
|
||||
static const int kFileList = 3;
|
||||
static const int kFileListScrollBar = 4;
|
||||
static const int kFileNameEditBox = 5;
|
||||
static const int kDeleteButton = 5;
|
||||
static const int kOpenDeleteButton = 5;
|
||||
static const int kSaveDeleteButton = 7;
|
||||
static const int kFileBrowserUIOpenDialogTemplateID = 2001;
|
||||
static const int kFileBrowserUISaveDialogTemplateID = 2002;
|
||||
static const int kFileBrowserUIOverwriteDialogTemplateID = 2003;
|
||||
static const int kFileBrowserUIBadNameDialogTemplateID = 2004;
|
||||
static const int kFileBrowserUISaveDialogUnobstructiveTemplateID = 2007;
|
||||
static const int kFileBrowserUIDeleteDialogTemplateID = 2008;
|
||||
static const int kFileBrowserUISaveDialogWithDeleteButtonTemplateID = 2009;
|
||||
|
||||
|
||||
static const int kOverwriteNoButton = 1;
|
||||
@@ -57,7 +60,7 @@ namespace PortabilityLayer
|
||||
class FileBrowserUIImpl
|
||||
{
|
||||
public:
|
||||
explicit FileBrowserUIImpl(const FileBrowserUI_DetailsCallbackAPI &callbackAPI);
|
||||
FileBrowserUIImpl(VirtualDirectory_t dir, const FileBrowserUI_DetailsCallbackAPI &callbackAPI);
|
||||
~FileBrowserUIImpl();
|
||||
|
||||
static void PubScrollBarCallback(void *captureContext, Widget *control, int part);
|
||||
@@ -111,6 +114,8 @@ namespace PortabilityLayer
|
||||
uint32_t m_doubleClickTime;
|
||||
bool m_haveFirstClick;
|
||||
|
||||
VirtualDirectory_t m_dir;
|
||||
|
||||
const FileBrowserUI_DetailsCallbackAPI m_api;
|
||||
};
|
||||
}
|
||||
@@ -128,7 +133,7 @@ static int16_t FileBrowserUIImpl_PopUpAlertUIFilter(void *context, Dialog *dialo
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
FileBrowserUIImpl::FileBrowserUIImpl(const FileBrowserUI_DetailsCallbackAPI &callbackAPI)
|
||||
FileBrowserUIImpl::FileBrowserUIImpl(VirtualDirectory_t dir, const FileBrowserUI_DetailsCallbackAPI &callbackAPI)
|
||||
: m_offset(0)
|
||||
, m_surface(nullptr)
|
||||
, m_window(nullptr)
|
||||
@@ -142,6 +147,7 @@ namespace PortabilityLayer
|
||||
, m_doubleClickTime(0)
|
||||
, m_haveFirstClick(false)
|
||||
, m_api(callbackAPI)
|
||||
, m_dir(dir)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,7 +157,7 @@ namespace PortabilityLayer
|
||||
{
|
||||
FileEntry *entries = *m_entries;
|
||||
for (size_t i = 0; i < m_numEntries; i++)
|
||||
m_api.m_freeFileDetailsCallback(entries[i].m_fileDetails);
|
||||
m_api.m_freeFileDetailsCallback(m_api.m_context, entries[i].m_fileDetails);
|
||||
}
|
||||
m_entries.Dispose();
|
||||
}
|
||||
@@ -207,7 +213,7 @@ namespace PortabilityLayer
|
||||
ResolveCachingColor blackColor = StdColors::Black();
|
||||
|
||||
const Point basePoint = Point::Create(16, 16 + font->GetMetrics().m_ascent);
|
||||
m_api.m_drawLabelsCallback(m_surface, basePoint);
|
||||
m_api.m_drawLabelsCallback(m_api.m_context, m_surface, basePoint);
|
||||
}
|
||||
|
||||
void FileBrowserUIImpl::DrawFileList()
|
||||
@@ -243,7 +249,7 @@ namespace PortabilityLayer
|
||||
Point itemStringPoint = Point::Create(itemRect.left + 2, itemRect.top + glyphOffset);
|
||||
m_surface->DrawStringConstrained(itemStringPoint, (*m_entries)[i].m_nameStr.ToShortStr(), m_rect, blackColor, font);
|
||||
|
||||
m_api.m_drawFileDetailsCallback(m_surface, itemStringPoint, m_rect, (*m_entries)[i].m_fileDetails);
|
||||
m_api.m_drawFileDetailsCallback(m_api.m_context, m_surface, itemStringPoint, m_rect, (*m_entries)[i].m_fileDetails);
|
||||
|
||||
itemRect.top += spacing;
|
||||
itemRect.bottom += spacing;
|
||||
@@ -294,11 +300,10 @@ namespace PortabilityLayer
|
||||
if (m_selectedIndex < 0)
|
||||
return;
|
||||
|
||||
|
||||
FileEntry *entries = *m_entries;
|
||||
|
||||
FileEntry &removedEntry = entries[m_selectedIndex];
|
||||
m_api.m_freeFileDetailsCallback(removedEntry.m_fileDetails);
|
||||
m_api.m_freeFileDetailsCallback(m_api.m_context, removedEntry.m_fileDetails);
|
||||
|
||||
for (size_t i = m_selectedIndex; i < m_numEntries - 1; i++)
|
||||
entries[i] = entries[i + 1];
|
||||
@@ -439,8 +444,19 @@ namespace PortabilityLayer
|
||||
|
||||
dialog->GetItems()[kOkayButton - 1].GetWidget()->SetEnabled(selection >= 0);
|
||||
|
||||
bool isDeleteValid = (selection >= 0);
|
||||
|
||||
if (isDeleteValid)
|
||||
{
|
||||
const FileBrowserUIImpl::FileEntry &entry = (*m_entries)[selection];
|
||||
isDeleteValid = m_api.m_isDeleteValidCallback(m_api.m_context, m_dir, entry.m_nameStr.ToShortStr());
|
||||
}
|
||||
|
||||
if (gs_currentFileBrowserUIMode == FileBrowserUI::Mode_Open)
|
||||
dialog->GetItems()[kDeleteButton - 1].GetWidget()->SetEnabled(selection >= 0);
|
||||
dialog->GetItems()[kOpenDeleteButton - 1].GetWidget()->SetEnabled(isDeleteValid);
|
||||
else if (gs_currentFileBrowserUIMode == FileBrowserUI::Mode_SaveWithDelete)
|
||||
dialog->GetItems()[kSaveDeleteButton - 1].GetWidget()->SetEnabled(isDeleteValid);
|
||||
|
||||
|
||||
DrawFileList();
|
||||
}
|
||||
@@ -585,16 +601,22 @@ namespace PortabilityLayer
|
||||
int windowHeight = 272;
|
||||
if (mode == Mode_Open)
|
||||
dialogID = kFileBrowserUIOpenDialogTemplateID;
|
||||
else if (mode == Mode_Save)
|
||||
else if (mode == Mode_SaveWithDelete || mode == Mode_SaveNoDelete)
|
||||
{
|
||||
if (PLDrivers::GetSystemServices()->IsTextInputObstructive())
|
||||
{
|
||||
dialogID = kFileBrowserUISaveDialogUnobstructiveTemplateID;
|
||||
windowHeight = 208;
|
||||
isObstructive = true;
|
||||
mode = Mode_SaveNoDelete; // HACK HACK HACK
|
||||
}
|
||||
else
|
||||
dialogID = kFileBrowserUISaveDialogTemplateID;
|
||||
{
|
||||
if (mode == Mode_SaveWithDelete)
|
||||
dialogID = kFileBrowserUISaveDialogWithDeleteButtonTemplateID;
|
||||
else
|
||||
dialogID = kFileBrowserUISaveDialogTemplateID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -602,7 +624,7 @@ namespace PortabilityLayer
|
||||
return false;
|
||||
}
|
||||
|
||||
FileBrowserUIImpl uiImpl(callbackAPI);
|
||||
FileBrowserUIImpl uiImpl(dirID, callbackAPI);
|
||||
|
||||
// Enumerate files
|
||||
IGpFileSystem *fs = PLDrivers::GetFileSystem();
|
||||
@@ -624,10 +646,10 @@ namespace PortabilityLayer
|
||||
if (!memcmp(nameExt, extension, extensionLength))
|
||||
{
|
||||
PLPasStr fnamePStr = PLPasStr(nameLength - extensionLength, fileName);
|
||||
if (!callbackAPI.m_filterFileCallback(dirID, fnamePStr))
|
||||
if (!callbackAPI.m_filterFileCallback(callbackAPI.m_context, dirID, fnamePStr))
|
||||
continue;
|
||||
|
||||
if (!uiImpl.AppendName(fileName, nameLength - extensionLength, callbackAPI.m_loadFileDetailsCallback(dirID, fnamePStr)))
|
||||
if (!uiImpl.AppendName(fileName, nameLength - extensionLength, callbackAPI.m_loadFileDetailsCallback(callbackAPI.m_context, dirID, fnamePStr)))
|
||||
{
|
||||
dirCursor->Destroy();
|
||||
return false;
|
||||
@@ -674,7 +696,7 @@ namespace PortabilityLayer
|
||||
const Rect scrollBarRect = dialog->GetItems()[kFileListScrollBar - 1].GetWidget()->GetRect();
|
||||
|
||||
EditboxWidget *editbox = nullptr;
|
||||
if (mode == Mode_Save)
|
||||
if (mode == Mode_SaveWithDelete || mode == Mode_SaveNoDelete)
|
||||
{
|
||||
editbox = static_cast<EditboxWidget*>(dialog->GetItems()[kFileNameEditBox - 1].GetWidget());
|
||||
editbox->SetCharacterFilter(&uiImpl, FileBrowserUIImpl::PubEditBoxCharFilter);
|
||||
@@ -725,7 +747,7 @@ namespace PortabilityLayer
|
||||
if (hit == kFileListScrollBar)
|
||||
uiImpl.SetScrollOffset(scrollBar->GetState());
|
||||
|
||||
if (hit == kOkayButton && mode == Mode_Save)
|
||||
if (hit == kOkayButton && (mode == Mode_SaveWithDelete || mode == Mode_SaveNoDelete))
|
||||
{
|
||||
IGpFileSystem *fs = PLDrivers::GetFileSystem();
|
||||
|
||||
@@ -734,7 +756,7 @@ namespace PortabilityLayer
|
||||
PLPasStr nameStr = editBox->GetString();
|
||||
if (nameStr.Length() == 0 || !fs->ValidateFilePath(nameStr.Chars(), nameStr.Length()))
|
||||
{
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
SysBeep(1);
|
||||
FileBrowserUIImpl::PopUpAlert(Rect::Create(0, 0, 135, 327), kFileBrowserUIBadNameDialogTemplateID, nullptr);
|
||||
hit = -1;
|
||||
}
|
||||
@@ -750,7 +772,7 @@ namespace PortabilityLayer
|
||||
{
|
||||
DialogTextSubstitutions substitutions(nameStr);
|
||||
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
SysBeep(1);
|
||||
int16_t subHit = FileBrowserUIImpl::PopUpAlert(Rect::Create(0, 0, 135, 327), kFileBrowserUIOverwriteDialogTemplateID, &substitutions);
|
||||
|
||||
if (subHit == kOverwriteNoButton)
|
||||
@@ -759,23 +781,32 @@ namespace PortabilityLayer
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == Mode_Open && hit == kDeleteButton)
|
||||
if ((mode == Mode_Open && hit == kOpenDeleteButton) || (mode == Mode_SaveWithDelete && hit == kSaveDeleteButton))
|
||||
{
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
SysBeep(1);
|
||||
int16_t subHit = FileBrowserUIImpl::PopUpAlert(Rect::Create(0, 0, 135, 327), kFileBrowserUIDeleteDialogTemplateID, &substitutions);
|
||||
|
||||
if (subHit == kOverwriteYesButton)
|
||||
{
|
||||
PLPasStr uiFileName = uiImpl.GetSelectedFileName();
|
||||
|
||||
bool deleted = false;
|
||||
if (composites)
|
||||
PortabilityLayer::FileManager::GetInstance()->DeleteCompositeFile(dirID, uiFileName);
|
||||
deleted = PortabilityLayer::FileManager::GetInstance()->DeleteCompositeFile(dirID, uiFileName);
|
||||
else
|
||||
PortabilityLayer::FileManager::GetInstance()->DeleteNonCompositeFile(dirID, uiFileName, extension);
|
||||
deleted = PortabilityLayer::FileManager::GetInstance()->DeleteNonCompositeFile(dirID, uiFileName, extension);
|
||||
|
||||
uiImpl.RemoveSelectedFile();
|
||||
dialog->GetItems()[kOkayButton - 1].GetWidget()->SetEnabled(false);
|
||||
dialog->GetItems()[kDeleteButton - 1].GetWidget()->SetEnabled(false);
|
||||
if (deleted)
|
||||
{
|
||||
callbackAPI.m_onDeletedCallback(callbackAPI.m_context, dirID, uiFileName);
|
||||
|
||||
uiImpl.RemoveSelectedFile();
|
||||
dialog->GetItems()[kOkayButton - 1].GetWidget()->SetEnabled(false);
|
||||
if (mode == Mode_Open)
|
||||
dialog->GetItems()[kOpenDeleteButton - 1].GetWidget()->SetEnabled(false);
|
||||
else if (mode == Mode_SaveWithDelete)
|
||||
dialog->GetItems()[kSaveDeleteButton - 1].GetWidget()->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
hit = -1;
|
||||
}
|
||||
@@ -793,7 +824,7 @@ namespace PortabilityLayer
|
||||
uiFileName = uiImpl.GetSelectedFileName();
|
||||
confirmed = true;
|
||||
}
|
||||
else if (mode == Mode_Save)
|
||||
else if (mode == Mode_SaveWithDelete || mode == Mode_SaveNoDelete)
|
||||
{
|
||||
uiFileName = editbox->GetString();
|
||||
confirmed = true;
|
||||
|
@@ -16,12 +16,16 @@ namespace PortabilityLayer
|
||||
|
||||
struct FileBrowserUI_DetailsCallbackAPI
|
||||
{
|
||||
void(*m_drawLabelsCallback)(DrawSurface *surface, const Point &basePoint);
|
||||
void(*m_drawFileDetailsCallback)(DrawSurface *surface, const Point &basePoint, const Rect &constraintRect, void *fileDetails);
|
||||
void *m_context;
|
||||
|
||||
void *(*m_loadFileDetailsCallback)(VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
void(*m_freeFileDetailsCallback)(void *fileDetails);
|
||||
bool(*m_filterFileCallback)(VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
void (*m_drawLabelsCallback)(void *context, DrawSurface *surface, const Point &basePoint);
|
||||
void (*m_drawFileDetailsCallback)(void *context, DrawSurface *surface, const Point &basePoint, const Rect &constraintRect, void *fileDetails);
|
||||
|
||||
void *(*m_loadFileDetailsCallback)(void *context, VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
void (*m_freeFileDetailsCallback)(void *context, void *fileDetails);
|
||||
bool (*m_filterFileCallback)(void *context, VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
bool (*m_isDeleteValidCallback)(void *context, VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
void (*m_onDeletedCallback)(void *context, VirtualDirectory_t dirID, const PLPasStr &filename);
|
||||
};
|
||||
|
||||
class FileBrowserUI
|
||||
@@ -30,7 +34,8 @@ namespace PortabilityLayer
|
||||
|
||||
enum Mode
|
||||
{
|
||||
Mode_Save,
|
||||
Mode_SaveNoDelete,
|
||||
Mode_SaveWithDelete,
|
||||
Mode_Open,
|
||||
};
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#include "PLErrorCodes.h"
|
||||
#include "PLSysCalls.h"
|
||||
|
||||
#include <vector>
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
@@ -282,7 +282,11 @@ namespace PortabilityLayer
|
||||
if (!FileManagerTools::ConstructFilename(extFN, initialFileName, ""))
|
||||
return false;
|
||||
|
||||
return FileBrowserUI::Prompt(FileBrowserUI::Mode_Save, dirID, extension, path, outPathLength, pathCapacity, initialFileName, promptText, composites, detailsAPI);
|
||||
FileBrowserUI::Mode mode = FileBrowserUI::Mode_SaveNoDelete;
|
||||
if (!PLDrivers::GetSystemServices()->HasNativeFileManager())
|
||||
mode = FileBrowserUI::Mode_SaveWithDelete;
|
||||
|
||||
return FileBrowserUI::Prompt(mode, dirID, extension, path, outPathLength, pathCapacity, initialFileName, promptText, composites, detailsAPI);
|
||||
}
|
||||
|
||||
bool FileManagerImpl::PromptOpenFile(VirtualDirectory_t dirID, const char *extension, char *path, size_t &outPathLength, size_t pathCapacity, const PLPasStr &promptText, bool composites, const FileBrowserUI_DetailsCallbackAPI &detailsAPI)
|
||||
|
@@ -91,9 +91,8 @@ namespace PortabilityLayer
|
||||
return output;
|
||||
}
|
||||
|
||||
bool GpArcResourceTypeTag::Load(const char *str)
|
||||
bool GpArcResourceTypeTag::Load(const char *str, size_t l)
|
||||
{
|
||||
size_t l = strlen(str);
|
||||
if (l < sizeof(m_id))
|
||||
{
|
||||
memcpy(m_id, str, l);
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class ResTypeID;
|
||||
@@ -10,7 +12,7 @@ namespace PortabilityLayer
|
||||
|
||||
static GpArcResourceTypeTag Encode(const ResTypeID &tag);
|
||||
|
||||
bool Load(const char *str);
|
||||
bool Load(const char *str, size_t strLen);
|
||||
bool Decode(ResTypeID &outTag);
|
||||
};
|
||||
}
|
||||
|
@@ -40,13 +40,9 @@ namespace
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream)
|
||||
void MacBinary2::SerializeHeader(unsigned char *mb2Header, const MacFileInfo &fileInfo)
|
||||
{
|
||||
const MacFileInfo &fileInfo = file->FileInfo();
|
||||
|
||||
uint8_t mb2Header[128];
|
||||
|
||||
memset(mb2Header, 0, sizeof(mb2Header));
|
||||
memset(mb2Header, 0, kHeaderSize);
|
||||
|
||||
mb2Header[MB2FileOffsets::Version] = 0;
|
||||
|
||||
@@ -87,7 +83,15 @@ namespace PortabilityLayer
|
||||
mb2Header[MB2FileOffsets::MinVersion] = 129;
|
||||
|
||||
BytePack::BigUInt16(mb2Header + MB2FileOffsets::Checksum, XModemCRC(mb2Header, 124, 0));
|
||||
}
|
||||
|
||||
void MacBinary2::WriteBin(const MacFileMem *file, GpIOStream *stream)
|
||||
{
|
||||
const MacFileInfo &fileInfo = file->FileInfo();
|
||||
|
||||
uint8_t mb2Header[128];
|
||||
|
||||
SerializeHeader(mb2Header, fileInfo);
|
||||
stream->Write(mb2Header, 128);
|
||||
|
||||
uint8_t *padding = mb2Header;
|
||||
|
@@ -1,19 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __PL_MACBINARY2_H__
|
||||
#define __PL_MACBINARY2_H__
|
||||
|
||||
class GpIOStream;
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class MacFileMem;
|
||||
struct MacFileInfo;
|
||||
|
||||
namespace MacBinary2
|
||||
{
|
||||
static const int kHeaderSize = 128;
|
||||
|
||||
void SerializeHeader(unsigned char *headerBytes, const MacFileInfo &macFileInfo);
|
||||
|
||||
void WriteBin(const MacFileMem *file, GpIOStream *stream);
|
||||
MacFileMem *ReadBin(GpIOStream *stream);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -81,7 +81,7 @@ namespace PortabilityLayer
|
||||
if (newSize != hdl->m_size)
|
||||
{
|
||||
void *newBuf = Realloc(hdl->m_contents, newSize);
|
||||
if (!newBuf)
|
||||
if (!newBuf && newSize != 0)
|
||||
return false;
|
||||
|
||||
hdl->m_contents = newBuf;
|
||||
|
@@ -128,6 +128,7 @@ namespace PortabilityLayer
|
||||
virtual void Init() override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
THandle<Menu> CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const override;
|
||||
THandle<Menu> DeserializeMenu(const void *resData) const override;
|
||||
THandle<Menu> GetMenuByID(int id) const override;
|
||||
|
||||
@@ -294,6 +295,60 @@ namespace PortabilityLayer
|
||||
// GP TODO: Dispose of menus properly
|
||||
}
|
||||
|
||||
THandle<Menu> MenuManagerImpl::CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
||||
const uint8_t titleLength = title.Length();
|
||||
|
||||
size_t stringDataLength = 1 + titleLength;
|
||||
size_t numMenuItems = 0;
|
||||
|
||||
MMHandleBlock *stringData = mm->AllocHandle(stringDataLength);
|
||||
if (!stringData)
|
||||
{
|
||||
mm->ReleaseHandle(stringData);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MMHandleBlock *menuData = mm->AllocHandle(sizeof(Menu) + sizeof(MenuItem) * (numMenuItems - 1));
|
||||
if (!menuData)
|
||||
{
|
||||
mm->ReleaseHandle(stringData);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Menu *menu = static_cast<Menu*>(menuData->m_contents);
|
||||
menu->menuID = menuID;
|
||||
menu->width = width;
|
||||
menu->height = height;
|
||||
menu->commandID = commandID;
|
||||
menu->enabled = true;
|
||||
menu->menuIndex = 0;
|
||||
menu->cumulativeOffset = 0;
|
||||
menu->unpaddedTitleWidth = 0;
|
||||
menu->isIcon = false;
|
||||
menu->haveMenuLayout = false;
|
||||
|
||||
uint8_t *stringDataStart = static_cast<uint8_t*>(stringData->m_contents);
|
||||
uint8_t *stringDest = stringDataStart;
|
||||
stringDest[0] = title.Length();
|
||||
memcpy(stringDest + 1, title.UChars(), title.Length());
|
||||
|
||||
menu->numMenuItems = numMenuItems;
|
||||
menu->stringBlobHandle = stringData;
|
||||
menu->prevMenu = nullptr;
|
||||
menu->nextMenu = nullptr;
|
||||
menu->layoutHintHorizontalOffset = 0;
|
||||
menu->layoutWidth = 0;
|
||||
menu->layoutBaseHeight = 0;
|
||||
menu->layoutFinalHeight = 0;
|
||||
menu->bottomItemsTruncated = 0;
|
||||
menu->topItemsTruncated = 0;
|
||||
|
||||
return THandle<Menu>(menuData);
|
||||
}
|
||||
|
||||
THandle<Menu> MenuManagerImpl::DeserializeMenu(const void *resData) const
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
@@ -23,6 +23,7 @@ namespace PortabilityLayer
|
||||
virtual void Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual THandle<Menu> CreateMenu(const PLPasStr &title, uint16_t menuID, bool enabled, uint16_t width, uint16_t height, uint16_t commandID) const = 0;
|
||||
virtual THandle<Menu> DeserializeMenu(const void *resData) const = 0;
|
||||
virtual THandle<Menu> GetMenuByID(int id) const = 0;
|
||||
|
||||
|
@@ -18,9 +18,18 @@ namespace PortabilityLayer
|
||||
memcpy(dest + 1, src, sz);
|
||||
}
|
||||
}
|
||||
|
||||
static BeepFunction_t gs_beepFunction = nullptr;
|
||||
}
|
||||
|
||||
void SysBeep(int duration)
|
||||
{
|
||||
PLDrivers::GetSystemServices()->Beep();
|
||||
if (!PLDrivers::GetSystemServices()->Beep())
|
||||
if (PortabilityLayer::gs_beepFunction != nullptr)
|
||||
PortabilityLayer::gs_beepFunction(duration);
|
||||
}
|
||||
|
||||
void SetBeepFunction(BeepFunction_t beepFunction)
|
||||
{
|
||||
PortabilityLayer::gs_beepFunction = beepFunction;
|
||||
}
|
||||
|
@@ -23,7 +23,11 @@ void PasStringCopy(const unsigned char *src, unsigned char *dest);
|
||||
template<size_t TSize>
|
||||
void PasStringCopy(const PortabilityLayer::PascalStrLiteral<TSize> &src, unsigned char *dest);
|
||||
|
||||
void SysBeep(int duration);
|
||||
void SysBeep(int duration);
|
||||
|
||||
typedef void (*BeepFunction_t)(int duration);
|
||||
void SetBeepFunction(BeepFunction_t beepFunction);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "PascalStrLiteral.h"
|
||||
|
@@ -886,14 +886,6 @@ ArrayView<PortabilityLayer::Widget*> Window::GetWidgets() const
|
||||
return ArrayView<PortabilityLayer::Widget*>(m_widgets, m_numWidgets);
|
||||
}
|
||||
|
||||
PortabilityLayer::Widget* Window::GetWidgetById() const
|
||||
{
|
||||
//for (size_t i = 0; i < m_numWidgets; i++)
|
||||
// m_widgets[i]->get
|
||||
//return ArrayView<PortabilityLayer::Widget*>(m_widgets, m_numWidgets);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Window::ReplaceWidget(PortabilityLayer::Widget *oldWidget, PortabilityLayer::Widget *newWidget)
|
||||
{
|
||||
for (size_t i = 0; i < m_numWidgets; i++)
|
||||
|
@@ -106,7 +106,6 @@ struct Window
|
||||
|
||||
bool AddWidget(PortabilityLayer::Widget *widget);
|
||||
ArrayView<PortabilityLayer::Widget*> GetWidgets() const;
|
||||
PortabilityLayer::Widget *GetWidgetById() const;
|
||||
bool ReplaceWidget(PortabilityLayer::Widget *oldWidget, PortabilityLayer::Widget *newWidget);
|
||||
|
||||
void FocusWidget(PortabilityLayer::Widget *widget);
|
||||
|
@@ -493,6 +493,71 @@ static void RedistributeError(int16_t *errorDiffusionNextRow, int16_t *errorDiff
|
||||
}
|
||||
}
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
bool FindBitSpan(uint32_t mask, int &outLowBit, int &outHighBit)
|
||||
{
|
||||
bool haveAnyBits = false;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (mask & (1 << i))
|
||||
{
|
||||
if (!haveAnyBits)
|
||||
{
|
||||
haveAnyBits = true;
|
||||
outLowBit = i;
|
||||
}
|
||||
outHighBit = i;
|
||||
}
|
||||
}
|
||||
|
||||
return haveAnyBits;
|
||||
}
|
||||
|
||||
int DecodeMaskRShift1(uint32_t mask)
|
||||
{
|
||||
int lowBit, highBit;
|
||||
if (!FindBitSpan(mask, lowBit, highBit))
|
||||
return 0;
|
||||
|
||||
return lowBit;
|
||||
}
|
||||
|
||||
int DecodeMaskRShift2(uint32_t mask)
|
||||
{
|
||||
int lowBit, highBit;
|
||||
if (!FindBitSpan(mask, lowBit, highBit))
|
||||
return 0;
|
||||
|
||||
int numBits = highBit - lowBit + 1;
|
||||
|
||||
int expandedBits = numBits;
|
||||
while (expandedBits < 8)
|
||||
expandedBits += numBits;
|
||||
|
||||
return expandedBits - 8;
|
||||
}
|
||||
|
||||
int DecodeMaskMultiplier(uint32_t mask)
|
||||
{
|
||||
int lowBit, highBit;
|
||||
if (!FindBitSpan(mask, lowBit, highBit))
|
||||
return 0;
|
||||
|
||||
int numBits = highBit - lowBit + 1;
|
||||
|
||||
int expandedBits = numBits;
|
||||
int expansionFactor = 1;
|
||||
while (expandedBits < 8)
|
||||
{
|
||||
expandedBits += numBits;
|
||||
expansionFactor = (expansionFactor << numBits) | 1;
|
||||
}
|
||||
|
||||
return expansionFactor;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds, bool errorDiffusion)
|
||||
{
|
||||
if (!pictHdl)
|
||||
@@ -572,9 +637,9 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
memcpy(&fileHeader, bmpBytes, sizeof(fileHeader));
|
||||
memcpy(&infoHeader, bmpBytes + sizeof(fileHeader), sizeof(infoHeader));
|
||||
|
||||
const uint16_t bpp = infoHeader.m_bitsPerPixel;
|
||||
uint16_t bpp = infoHeader.m_bitsPerPixel;
|
||||
|
||||
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24)
|
||||
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)
|
||||
return;
|
||||
|
||||
uint32_t numColors = infoHeader.m_numColors;
|
||||
@@ -584,6 +649,18 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
if (numColors == 0 && bpp <= 8)
|
||||
numColors = (1 << bpp);
|
||||
|
||||
LEUInt32_t masks[4];
|
||||
int maskRShift1[4];
|
||||
int maskRShift2[4];
|
||||
int maskMultiplier[4];
|
||||
bool haveMasks = false;
|
||||
if (infoHeader.m_thisStructureSize >= sizeof(PortabilityLayer::BitmapInfoHeader) + sizeof(uint32_t) * 4)
|
||||
{
|
||||
const uint8_t *masksLoc = bmpBytes + sizeof(fileHeader) + sizeof(PortabilityLayer::BitmapInfoHeader);
|
||||
memcpy(masks, masksLoc, 16);
|
||||
haveMasks = true;
|
||||
}
|
||||
|
||||
const uint8_t *ctabLoc = bmpBytes + sizeof(fileHeader) + infoHeader.m_thisStructureSize;
|
||||
|
||||
const size_t ctabSize = numColors * sizeof(PortabilityLayer::BitmapColorTableEntry);
|
||||
@@ -592,6 +669,57 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
if (ctabSize > availCTabBytes)
|
||||
return;
|
||||
|
||||
const uint32_t compressionCode = static_cast<uint32_t>(infoHeader.m_compression);
|
||||
if (bpp == 16)
|
||||
{
|
||||
if (compressionCode == 0)
|
||||
{
|
||||
haveMasks = true;
|
||||
masks[0] = (0x1f << 10);
|
||||
masks[1] = (0x1f << 5);
|
||||
masks[2] = (0x1f << 0);
|
||||
masks[3] = (1 << 15);
|
||||
}
|
||||
else if (compressionCode == 3)
|
||||
{
|
||||
if (!haveMasks)
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if (bpp == 32)
|
||||
{
|
||||
if (compressionCode == 0)
|
||||
{
|
||||
haveMasks = true;
|
||||
masks[0] = (0xff << 16);
|
||||
masks[1] = (0xff << 8);
|
||||
masks[2] = (0xff << 0);
|
||||
masks[3] = (0xff << 24);
|
||||
}
|
||||
if (compressionCode == 3)
|
||||
{
|
||||
if (!haveMasks)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compressionCode != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (haveMasks)
|
||||
{
|
||||
for (int mi = 0; mi < 4; mi++)
|
||||
{
|
||||
maskRShift1[mi] = PortabilityLayer::DecodeMaskRShift1(masks[mi]);
|
||||
maskRShift2[mi] = PortabilityLayer::DecodeMaskRShift2(masks[mi]);
|
||||
maskMultiplier[mi] = PortabilityLayer::DecodeMaskMultiplier(masks[mi]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bpp <= 8)
|
||||
{
|
||||
// Perform palette mapping
|
||||
@@ -672,7 +800,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
int16_t *errorDiffusionNextRow = nullptr;
|
||||
int16_t *errorDiffusionCurrentRow = nullptr;
|
||||
|
||||
if ((bpp == 16 || bpp == 24) && errorDiffusion)
|
||||
if ((bpp == 16 || bpp == 24 || bpp == 32) && errorDiffusion)
|
||||
{
|
||||
errorDiffusionBuffer = static_cast<int16_t*>(memManager->Alloc(sizeof(int16_t) * numCopyCols * 2 * 3));
|
||||
if (!errorDiffusionBuffer)
|
||||
@@ -739,12 +867,13 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const uint8_t srcLow = currentSourceRow[srcColIndex * 2 + 0];
|
||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||
|
||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
||||
const unsigned int b = (combinedValue & 0x1f);
|
||||
const unsigned int g = ((combinedValue >> 5) & 0x1f);
|
||||
const unsigned int r = ((combinedValue >> 10) & 0x1f);
|
||||
const uint32_t combinedValue = srcLow | (srcHigh << 8);
|
||||
|
||||
if (r + g + b > 46)
|
||||
uint8_t rgb[3];
|
||||
for (unsigned int ch = 0; ch < 3; ch++)
|
||||
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
|
||||
|
||||
if (rgb[0] + rgb[1] + rgb[2] > 382)
|
||||
currentDestRow[destColIndex] = 0;
|
||||
else
|
||||
currentDestRow[destColIndex] = 1;
|
||||
@@ -763,15 +892,12 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||
|
||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
||||
const unsigned int b = (combinedValue & 0x1f);
|
||||
const unsigned int g = ((combinedValue >> 5) & 0x1f);
|
||||
const unsigned int r = ((combinedValue >> 10) & 0x1f);
|
||||
|
||||
const unsigned int xr = (r << 5) | (r >> 2);
|
||||
const unsigned int xg = (g << 5) | (g >> 2);
|
||||
const unsigned int xb = (b << 5) | (b >> 2);
|
||||
uint8_t rgb[3];
|
||||
for (unsigned int ch = 0; ch < 3; ch++)
|
||||
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
|
||||
|
||||
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(xr, xg, xb, 255));
|
||||
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(rgb[0], rgb[1], rgb[2], 255));
|
||||
|
||||
currentDestRow[destColIndex] = colorIndex;
|
||||
}
|
||||
@@ -787,15 +913,12 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||
|
||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
||||
const unsigned int b = (combinedValue & 0x1f);
|
||||
const unsigned int g = ((combinedValue >> 5) & 0x1f);
|
||||
const unsigned int r = ((combinedValue >> 10) & 0x1f);
|
||||
|
||||
const unsigned int xr = (r << 5) | (r >> 2);
|
||||
const unsigned int xg = (g << 5) | (g >> 2);
|
||||
const unsigned int xb = (b << 5) | (b >> 2);
|
||||
uint8_t rgb[3];
|
||||
for (unsigned int ch = 0; ch < 3; ch++)
|
||||
rgb[ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
|
||||
|
||||
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, xr, xg, xb, col, numCopyCols);
|
||||
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, rgb[0], rgb[1], rgb[2], col, numCopyCols);
|
||||
|
||||
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(wp.m_8[0], wp.m_8[1], wp.m_8[2], 255));
|
||||
PortabilityLayer::RGBAColor resultColor = stdPalette->GetColors()[colorIndex];
|
||||
@@ -816,15 +939,11 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const size_t srcColIndex = col + firstSourceCol;
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
const uint8_t srcLow = currentSourceRow[srcColIndex * 2 + 0];
|
||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||
const uint8_t r = currentSourceRow[srcColIndex * 3 + 2];
|
||||
const uint8_t g = currentSourceRow[srcColIndex * 3 + 1];
|
||||
const uint8_t b = currentSourceRow[srcColIndex * 3 + 0];
|
||||
|
||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
||||
const unsigned int b = (combinedValue & 0x1f);
|
||||
const unsigned int g = ((combinedValue >> 5) & 0x1f);
|
||||
const unsigned int r = ((combinedValue >> 10) & 0x1f);
|
||||
|
||||
if (r + g + b > 46)
|
||||
if (r + g + b > 382)
|
||||
currentDestRow[destColIndex] = 0;
|
||||
else
|
||||
currentDestRow[destColIndex] = 1;
|
||||
@@ -867,6 +986,62 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bpp == 32)
|
||||
{
|
||||
if (destFormat == GpPixelFormats::kBW1)
|
||||
{
|
||||
for (size_t col = 0; col < numCopyCols; col++)
|
||||
{
|
||||
const size_t srcColIndex = col + firstSourceCol;
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
const uint8_t r = currentSourceRow[srcColIndex * 4 + 2];
|
||||
const uint8_t g = currentSourceRow[srcColIndex * 4 + 1];
|
||||
const uint8_t b = currentSourceRow[srcColIndex * 4 + 0];
|
||||
|
||||
if (r + g + b > 382)
|
||||
currentDestRow[destColIndex] = 0;
|
||||
else
|
||||
currentDestRow[destColIndex] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!errorDiffusion)
|
||||
{
|
||||
for (size_t col = 0; col < numCopyCols; col++)
|
||||
{
|
||||
const size_t srcColIndex = col + firstSourceCol;
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
const uint8_t r = currentSourceRow[srcColIndex * 4 + 2];
|
||||
const uint8_t g = currentSourceRow[srcColIndex * 4 + 1];
|
||||
const uint8_t b = currentSourceRow[srcColIndex * 4 + 0];
|
||||
|
||||
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(r, g, b, 255));
|
||||
|
||||
currentDestRow[destColIndex] = colorIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t col = 0; col < numCopyCols; col++)
|
||||
{
|
||||
const size_t srcColIndex = col + firstSourceCol;
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
ErrorDiffusionWorkPixel wp = ApplyErrorDiffusion(errorDiffusionCurrentRow, currentSourceRow[srcColIndex * 4 + 2], currentSourceRow[srcColIndex * 4 + 1], currentSourceRow[srcColIndex * 4 + 0], col, numCopyCols);
|
||||
|
||||
uint8_t colorIndex = stdPalette->MapColorLUT(PortabilityLayer::RGBAColor::Create(wp.m_8[0], wp.m_8[1], wp.m_8[2], 255));
|
||||
PortabilityLayer::RGBAColor resultColor = stdPalette->GetColors()[colorIndex];
|
||||
|
||||
RedistributeError(errorDiffusionNextRow, errorDiffusionCurrentRow, wp.m_16[0], wp.m_16[1], wp.m_16[2], resultColor.r, resultColor.g, resultColor.b, col, numCopyCols);
|
||||
|
||||
currentDestRow[destColIndex] = colorIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentSourceRow -= sourcePitch;
|
||||
currentDestRow += destPitch;
|
||||
@@ -907,7 +1082,7 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
const unsigned int srcIndex = (currentSourceRow[srcColIndex / 8] >> (8 - ((srcColIndex & 7) + 1))) & 0x01;
|
||||
currentDestRow32[destColIndex] = srcIndex ? blackColor32 : whiteColor32;
|
||||
currentDestRow32[destColIndex] = unpackedColors[srcIndex];
|
||||
}
|
||||
}
|
||||
else if (bpp == 4)
|
||||
@@ -943,17 +1118,10 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
const uint8_t srcHigh = currentSourceRow[srcColIndex * 2 + 1];
|
||||
|
||||
const unsigned int combinedValue = srcLow | (srcHigh << 8);
|
||||
const unsigned int b = (combinedValue & 0x1f);
|
||||
const unsigned int g = ((combinedValue >> 5) & 0x1f);
|
||||
const unsigned int r = ((combinedValue >> 10) & 0x1f);
|
||||
|
||||
const unsigned int xr = (r << 5) | (r >> 2);
|
||||
const unsigned int xg = (g << 5) | (g >> 2);
|
||||
const unsigned int xb = (b << 5) | (b >> 2);
|
||||
for (unsigned int ch = 0; ch < 3; ch++)
|
||||
currentDestRowBytes[destColIndex * 4 + ch] = (((combinedValue & masks[ch]) >> maskRShift1[ch]) * maskMultiplier[ch]) >> maskRShift2[ch];
|
||||
|
||||
currentDestRowBytes[destColIndex * 4 + 0] = xr;
|
||||
currentDestRowBytes[destColIndex * 4 + 1] = xg;
|
||||
currentDestRowBytes[destColIndex * 4 + 2] = xb;
|
||||
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
@@ -970,6 +1138,19 @@ void DrawSurface::DrawPicture(THandle<BitmapImage> pictHdl, const Rect &bounds,
|
||||
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
else if (bpp == 32)
|
||||
{
|
||||
for (size_t col = 0; col < numCopyCols; col++)
|
||||
{
|
||||
const size_t srcColIndex = col + firstSourceCol;
|
||||
const size_t destColIndex = col + firstDestCol;
|
||||
|
||||
currentDestRowBytes[destColIndex * 4 + 0] = currentSourceRow[srcColIndex * 4 + 2];
|
||||
currentDestRowBytes[destColIndex * 4 + 1] = currentSourceRow[srcColIndex * 4 + 1];
|
||||
currentDestRowBytes[destColIndex * 4 + 2] = currentSourceRow[srcColIndex * 4 + 0];
|
||||
currentDestRowBytes[destColIndex * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
currentSourceRow -= sourcePitch;
|
||||
currentDestRowBytes += destPitch;
|
||||
|
@@ -40,6 +40,61 @@ static const char *kPICTExtension = ".bmp";
|
||||
|
||||
typedef ResourceValidationRules::ResourceValidationRule ResourceValidationRule_t;
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
class ResourceArchiveZipFileIterator : public IResourceIterator
|
||||
{
|
||||
public:
|
||||
explicit ResourceArchiveZipFileIterator(PortabilityLayer::ZipFileProxy *proxy);
|
||||
|
||||
void Destroy() override;
|
||||
bool GetOne(ResTypeID &resTypeID, int16_t &outID) override;
|
||||
|
||||
private:
|
||||
~ResourceArchiveZipFileIterator();
|
||||
|
||||
PortabilityLayer::ZipFileProxy *m_proxy;
|
||||
size_t m_numFiles;
|
||||
size_t m_currentIndex;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
PortabilityLayer::ResourceArchiveZipFileIterator::ResourceArchiveZipFileIterator(PortabilityLayer::ZipFileProxy *proxy)
|
||||
: m_proxy(proxy)
|
||||
, m_numFiles(proxy->NumFiles())
|
||||
, m_currentIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PortabilityLayer::ResourceArchiveZipFileIterator::Destroy()
|
||||
{
|
||||
this->~ResourceArchiveZipFileIterator();
|
||||
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
||||
}
|
||||
|
||||
bool PortabilityLayer::ResourceArchiveZipFileIterator::GetOne(ResTypeID &resTypeID, int16_t &outID)
|
||||
{
|
||||
while (m_currentIndex != m_numFiles)
|
||||
{
|
||||
const size_t index = m_currentIndex++;
|
||||
|
||||
const char *name = nullptr;
|
||||
size_t nameLength = 0;
|
||||
m_proxy->GetFileName(index, name, nameLength);
|
||||
|
||||
const bool isParseable = ResourceArchiveZipFile::ParseResFromName(name, nameLength, resTypeID, outID);
|
||||
if (isParseable)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PortabilityLayer::ResourceArchiveZipFileIterator::~ResourceArchiveZipFileIterator()
|
||||
{
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// Validation here is only intended to be minimal, to ensure later checks can determine the format size and do certain operations
|
||||
@@ -433,6 +488,93 @@ namespace PortabilityLayer
|
||||
return haveAny;
|
||||
}
|
||||
|
||||
IResourceIterator *ResourceArchiveZipFile::EnumerateResources() const
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
void *storage = mm->Alloc(sizeof(ResourceArchiveZipFileIterator));
|
||||
if (!storage)
|
||||
return nullptr;
|
||||
|
||||
return new (storage) ResourceArchiveZipFileIterator(m_zipFileProxy);
|
||||
}
|
||||
|
||||
bool ResourceArchiveZipFile::ParseResFromName(const char *name, size_t nameLength, ResTypeID &outResTypeID, int16_t &outID)
|
||||
{
|
||||
size_t slashPos = nameLength;
|
||||
for (size_t i = 0; i < nameLength; i++)
|
||||
{
|
||||
if (name[i] == '/')
|
||||
{
|
||||
slashPos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slashPos == nameLength)
|
||||
return false;
|
||||
|
||||
GpArcResourceTypeTag resTag;
|
||||
if (!resTag.Load(name, slashPos))
|
||||
return false;
|
||||
|
||||
if (!resTag.Decode(outResTypeID))
|
||||
return false;
|
||||
|
||||
int validationRule = 0;
|
||||
const char *expectedExtension = GetFileExtensionForResType(outResTypeID, validationRule);
|
||||
|
||||
const size_t idStart = slashPos + 1;
|
||||
if (idStart == nameLength)
|
||||
return false;
|
||||
|
||||
bool isNegative = false;
|
||||
size_t digitsStart = idStart;
|
||||
|
||||
if (name[idStart] == '-')
|
||||
{
|
||||
isNegative = true;
|
||||
digitsStart++;
|
||||
}
|
||||
|
||||
size_t digitsEnd = nameLength;
|
||||
int32_t resID = 0;
|
||||
for (size_t i = digitsStart; i < nameLength; i++)
|
||||
{
|
||||
if (name[i] == '.')
|
||||
{
|
||||
digitsEnd = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char digit = name[i];
|
||||
if (digit < '0' || digit > '9')
|
||||
return false;
|
||||
|
||||
int32_t digitNumber = static_cast<int32_t>(digit) - '0';
|
||||
resID *= 10;
|
||||
if (isNegative)
|
||||
resID -= digitNumber;
|
||||
else
|
||||
resID += digitNumber;
|
||||
|
||||
if (resID < -32768 || resID > 32767)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
outID = static_cast<int16_t>(resID);
|
||||
|
||||
const size_t extAvailable = nameLength - digitsEnd;
|
||||
if (strlen(expectedExtension) != extAvailable)
|
||||
return false;
|
||||
|
||||
if (memcmp(name + digitsEnd, expectedExtension, extAvailable) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResourceArchiveZipFile::IndexResource(const ResTypeID &resTypeID, int id, size_t &outIndex, int &outValidationRule) const
|
||||
{
|
||||
const char *extension = GetFileExtensionForResType(resTypeID, outValidationRule);
|
||||
@@ -461,6 +603,11 @@ namespace PortabilityLayer
|
||||
handle = ref->m_handle;
|
||||
else
|
||||
{
|
||||
const size_t resSize = m_zipFileProxy->GetFileSize(index);
|
||||
|
||||
if (resSize > kMaxResourceSize)
|
||||
return THandle<void>();
|
||||
|
||||
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||
if (!handle)
|
||||
return THandle<void>();
|
||||
@@ -468,7 +615,7 @@ namespace PortabilityLayer
|
||||
handle->m_rmSelfRef = ref;
|
||||
ref->m_handle = handle;
|
||||
ref->m_resID = static_cast<int16_t>(id);
|
||||
ref->m_size = m_zipFileProxy->GetFileSize(index);
|
||||
ref->m_size = resSize;
|
||||
}
|
||||
|
||||
if (handle->m_contents == nullptr && load)
|
||||
|
@@ -180,6 +180,9 @@ namespace PortabilityLayer
|
||||
|
||||
bool AudioChannelImpl::AddBuffer(IGpAudioBuffer *buffer, bool blocking)
|
||||
{
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
buffer->AddRef();
|
||||
|
||||
AudioCommand cmd;
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include "RGBAColor.h"
|
||||
#include "Vec2i.h"
|
||||
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
struct QDPictDecodeState
|
||||
|
@@ -1,32 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct Rect;
|
||||
class GpIOStream;
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct RGBAColor;
|
||||
struct QDPictEmitScanlineParameters;
|
||||
|
||||
enum QDPictBlitSourceType
|
||||
{
|
||||
QDPictBlitSourceType_1Bit,
|
||||
QDPictBlitSourceType_Indexed1Bit,
|
||||
QDPictBlitSourceType_Indexed2Bit,
|
||||
QDPictBlitSourceType_Indexed4Bit,
|
||||
QDPictBlitSourceType_Indexed8Bit,
|
||||
QDPictBlitSourceType_RGB15,
|
||||
QDPictBlitSourceType_RGB24_Interleaved,
|
||||
QDPictBlitSourceType_RGB24_Multiplane,
|
||||
};
|
||||
|
||||
bool QDPictBlitSourceType_IsIndexed(QDPictBlitSourceType sourceType);
|
||||
|
||||
class QDPictEmitContext
|
||||
{
|
||||
class GpIOStream;
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct RGBAColor;
|
||||
struct QDPictEmitScanlineParameters;
|
||||
|
||||
enum QDPictBlitSourceType
|
||||
{
|
||||
QDPictBlitSourceType_1Bit,
|
||||
QDPictBlitSourceType_Indexed1Bit,
|
||||
QDPictBlitSourceType_Indexed2Bit,
|
||||
QDPictBlitSourceType_Indexed4Bit,
|
||||
QDPictBlitSourceType_Indexed8Bit,
|
||||
QDPictBlitSourceType_RGB15,
|
||||
QDPictBlitSourceType_RGB24_Interleaved,
|
||||
QDPictBlitSourceType_RGB24_Multiplane,
|
||||
};
|
||||
|
||||
bool QDPictBlitSourceType_IsIndexed(QDPictBlitSourceType sourceType);
|
||||
|
||||
class QDPictEmitContext
|
||||
{
|
||||
public:
|
||||
enum ErrorCode
|
||||
{
|
||||
@@ -40,14 +40,14 @@ namespace PortabilityLayer
|
||||
kMalformedOpcode,
|
||||
kUnsupportedOpcode,
|
||||
};
|
||||
|
||||
virtual bool SpecifyFrame(const Rect &rect) = 0;
|
||||
virtual Rect ConstrainRegion(const Rect &rect) const = 0;
|
||||
virtual void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters ¶ms) = 0;
|
||||
virtual void BlitScanlineAndAdvance(const void *) = 0;
|
||||
virtual bool EmitQTContent(GpIOStream *stream, uint32_t dataSize, bool isCompressed) = 0;
|
||||
|
||||
virtual bool SpecifyFrame(const Rect &rect) = 0;
|
||||
virtual Rect ConstrainRegion(const Rect &rect) const = 0;
|
||||
virtual void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters ¶ms) = 0;
|
||||
virtual void BlitScanlineAndAdvance(const void *) = 0;
|
||||
virtual bool EmitQTContent(GpIOStream *stream, uint32_t dataSize, bool isCompressed) = 0;
|
||||
virtual bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) = 0;
|
||||
|
||||
virtual void ReportError(int errorType, int errorSubtype) { }
|
||||
};
|
||||
virtual void ReportError(int errorType, int errorSubtype) { }
|
||||
};
|
||||
}
|
||||
|
@@ -55,9 +55,9 @@ namespace PortabilityLayer
|
||||
memcpy(&v2Version, v2Header + 4, 2);
|
||||
|
||||
// In version 2 header, v2Version == -1
|
||||
// Followed by fixed-point bounding rectangle (16 bytes) and 4 reserved
|
||||
// Followed by 2-byte reserved (usually -1), fixed-point bounding rectangle (16 bytes) and 4 reserved (usually 0)
|
||||
// In ext. version 2 header, v2Version == -2
|
||||
// Followed by 2-byte reserved, horizontal DPI (fixed point, 4 bytes), vertical DPI (fixed point, 4 bytes) optimal source rect (8 bytes), and 2 reserved
|
||||
// Followed by 2-byte reserved (0), horizontal DPI (fixed point, 4 bytes), vertical DPI (fixed point, 4 bytes) optimal source rect (8 bytes), and 2 reserved
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@@ -27,6 +27,12 @@ namespace PortabilityLayer
|
||||
int16_t m_resID;
|
||||
};
|
||||
|
||||
struct IResourceIterator
|
||||
{
|
||||
virtual void Destroy() = 0;
|
||||
virtual bool GetOne(ResTypeID &resTypeID, int16_t &outID) = 0;
|
||||
};
|
||||
|
||||
struct IResourceArchive
|
||||
{
|
||||
virtual void Destroy() = 0;
|
||||
@@ -35,6 +41,8 @@ namespace PortabilityLayer
|
||||
|
||||
virtual bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const = 0;
|
||||
virtual bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const = 0;
|
||||
|
||||
virtual IResourceIterator *EnumerateResources() const = 0;
|
||||
};
|
||||
|
||||
class ResourceArchiveBase : public IResourceArchive
|
||||
@@ -43,9 +51,13 @@ namespace PortabilityLayer
|
||||
static const char *GetFileExtensionForResType(const ResTypeID &resTypeID, int &outValidationRule);
|
||||
};
|
||||
|
||||
class ResourceArchiveZipFileIterator;
|
||||
|
||||
class ResourceArchiveZipFile final : public ResourceArchiveBase
|
||||
{
|
||||
public:
|
||||
friend class ResourceArchiveZipFileIterator;
|
||||
|
||||
static ResourceArchiveZipFile *Create(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream);
|
||||
void Destroy() override;
|
||||
|
||||
@@ -54,7 +66,14 @@ namespace PortabilityLayer
|
||||
bool HasAnyResourcesOfType(const ResTypeID &resTypeID) const override;
|
||||
bool FindFirstResourceOfType(const ResTypeID &resTypeID, int16_t &outID) const override;
|
||||
|
||||
IResourceIterator *EnumerateResources() const override;
|
||||
|
||||
static bool ParseResFromName(const char *name, size_t nameLength, ResTypeID &outResTypeID, int16_t &outID);
|
||||
|
||||
|
||||
private:
|
||||
static const size_t kMaxResourceSize = 32 * 1024 * 1024;
|
||||
|
||||
ResourceArchiveZipFile(ZipFileProxy *zipFileProxy, bool proxyIsShared, GpIOStream *stream, ResourceArchiveRef *resourceHandles);
|
||||
~ResourceArchiveZipFile();
|
||||
|
||||
|
Reference in New Issue
Block a user