Filled in image.cpp. Also switched on WIC since we'll need it for uiArea, though uiTable will still need classic GDI. Now let's integrate this into uiTable.
This commit is contained in:
parent
3aee505f4e
commit
a858300f25
|
@ -78,7 +78,7 @@ set(_LIBUI_INCLUDEDIRS _LIBUI_INCLUDEDIRS PARENT_SCOPE)
|
||||||
|
|
||||||
# TODO prune this list
|
# TODO prune this list
|
||||||
set(_LIBUI_LIBS
|
set(_LIBUI_LIBS
|
||||||
user32 kernel32 gdi32 comctl32 uxtheme msimg32 comdlg32 d2d1 dwrite ole32 oleaut32 oleacc uuid
|
user32 kernel32 gdi32 comctl32 uxtheme msimg32 comdlg32 d2d1 dwrite ole32 oleaut32 oleacc uuid windowscodecs
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
#include "uipriv_windows.hpp"
|
#include "uipriv_windows.hpp"
|
||||||
// stubbed out windows image list implementation.
|
|
||||||
// Required for uiTable control, but windows implemenation
|
IWICImagingFactory *uiprivWICFactory = NULL;
|
||||||
// doesn't currently have image support.
|
|
||||||
|
HRESULT uiprivInitImage(void)
|
||||||
|
{
|
||||||
|
return CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
IID_IWICImagingFactory, (void **) (&uiprivWICFactory));
|
||||||
|
}
|
||||||
|
|
||||||
|
void uiprivUninitImage(void)
|
||||||
|
{
|
||||||
|
uiprivWICFactory->Release();
|
||||||
|
uiprivWICFactory = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct uiImage {
|
struct uiImage {
|
||||||
double width;
|
double width;
|
||||||
double height;
|
double height;
|
||||||
// HIMAGELIST images;
|
std::vector<IWICBitmap *> *bitmaps;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiImage *uiNewImage(double width, double height)
|
uiImage *uiNewImage(double width, double height)
|
||||||
|
@ -16,16 +27,132 @@ uiImage *uiNewImage(double width, double height)
|
||||||
i = uiprivNew(uiImage);
|
i = uiprivNew(uiImage);
|
||||||
i->width = width;
|
i->width = width;
|
||||||
i->height = height;
|
i->height = height;
|
||||||
|
i->bitmaps = new std::vector<IWICBitmap *>;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiFreeImage(uiImage *i)
|
void uiFreeImage(uiImage *i)
|
||||||
{
|
{
|
||||||
|
for (IWICBitmap *b : *(i->bitmaps))
|
||||||
|
b->Release();
|
||||||
|
delete i->bitmaps;
|
||||||
uiprivFree(i);
|
uiprivFree(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int pixelStride)
|
void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int pixelStride)
|
||||||
{
|
{
|
||||||
// not implemented
|
IWICBitmap *b;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = uiprivWICFactory->CreateBitmapFromMemory(pixelWidth, pixelHeight,
|
||||||
|
GUID_WICPixelFormat32bppRGBA, pixelStride,
|
||||||
|
pixelStride * pixelHeight, (BYTE *) pixels,
|
||||||
|
&b);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT(L"error calling CreateBitmapFromMemory() in uiImageAppend()", hr);
|
||||||
|
i->bitmaps->push_back(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct matcher {
|
||||||
|
IWICBitmap *best;
|
||||||
|
int distX;
|
||||||
|
int distY;
|
||||||
|
int targetX;
|
||||||
|
int targetY;
|
||||||
|
bool foundLarger;
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO is this the right algorithm?
|
||||||
|
static void match(IWICBitmap *b, struct matcher *m)
|
||||||
|
{
|
||||||
|
UINT ux, uy;
|
||||||
|
int x, y;
|
||||||
|
int x2, y2;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = b->GetSize(&ux, &uy);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT(L"error calling GetSize() in match()", hr);
|
||||||
|
x = ux;
|
||||||
|
y = uy;
|
||||||
|
if (m->best == NULL)
|
||||||
|
goto writeMatch;
|
||||||
|
|
||||||
|
if (x < m->targetX && y < m->targetY)
|
||||||
|
if (m->foundLarger)
|
||||||
|
// always prefer larger ones
|
||||||
|
return;
|
||||||
|
if (x >= m->targetX && y >= m->targetY && !m->foundLarger)
|
||||||
|
// we set foundLarger below
|
||||||
|
goto writeMatch;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||||
|
x2 = abs(m->targetX - x);
|
||||||
|
y2 = abs(m->targetY - y);
|
||||||
|
if (x2 < m->distX && y2 < m->distY)
|
||||||
|
goto writeMatch;
|
||||||
|
|
||||||
|
// TODO weight one dimension? threshhold?
|
||||||
|
return;
|
||||||
|
|
||||||
|
writeMatch:
|
||||||
|
// must set this here too; otherwise the first image will never have ths set
|
||||||
|
if (x >= m->targetX && y >= m->targetY && !m->foundLarger)
|
||||||
|
m->foundLarger = true;
|
||||||
|
m->best = b;
|
||||||
|
m->distX = abs(m->targetX - x);
|
||||||
|
m->distY = abs(m->targetY - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
IWICBitmap *uiprivImageAppropriateForDC(uiImage *i, HDC dc)
|
||||||
|
{
|
||||||
|
struct matcher m;
|
||||||
|
|
||||||
|
m.best = NULL;
|
||||||
|
m.distX = INT_MAX;
|
||||||
|
m.distY = INT_MAX;
|
||||||
|
m.targetX = i->width * GetDeviceCaps(dc, LOGPIXELSX);
|
||||||
|
m.targetY = i->height * GetDeviceCaps(dc, LOGPIXELSY);
|
||||||
|
m.foundLarger = false;
|
||||||
|
for (IWICBitmap *b : *(i->bitmaps))
|
||||||
|
match(b, &m);
|
||||||
|
return m.best;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO see if we can really pass NULL to CreateDIBSection()'s HDC parameter, and if so, use HBITMAPs before WIC maybe?
|
||||||
|
HBITMAP uiprivWICToGDI(IWICBitmap *b, HDC dc)
|
||||||
|
{
|
||||||
|
BITMAPINFO bmi;
|
||||||
|
UINT width, height;
|
||||||
|
HBITMAP hb;
|
||||||
|
VOID *bits;
|
||||||
|
BITMAP bmp;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
ZeroMemory(&bmi, sizeof (BITMAPINFO));
|
||||||
|
bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
||||||
|
hr = b->GetSize(&width, &height);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT(L"error calling GetSize() in uiprivWICToGDI()", hr);
|
||||||
|
bmi.bmiHeader.biWidth = width;
|
||||||
|
bmi.bmiHeader.biHeight = -((int) height);
|
||||||
|
bmi.bmiHeader.biPlanes = 1;
|
||||||
|
bmi.bmiHeader.biBitCount = 32;
|
||||||
|
bmi.bmiHeader.biCompression = BI_RGB;
|
||||||
|
hb = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS,
|
||||||
|
&bits, NULL, 0);
|
||||||
|
if (hb == NULL)
|
||||||
|
logLastError(L"error calling CreateDIBSection() in uiprivWICToGDI()");
|
||||||
|
|
||||||
|
// now we need to figure out the stride of the image data GDI gave us
|
||||||
|
// TODO find out if CreateDIBSection fills that in bmi for us
|
||||||
|
if (GetObject(hb, sizeof (BITMAP), &bmp) == 0)
|
||||||
|
logLastError(L"error calling GetObject() in uiprivWICToGDI()");
|
||||||
|
hr = b->CopyPixels(NULL, bmp.bmWidthBytes,
|
||||||
|
bmp.bmWidthBytes * bmp.bmHeight, (BYTE *) bits);
|
||||||
|
if (hr != S_OK)
|
||||||
|
logHRESULT(L"error calling CopyPixels() in uiprivWICToGDI()", hr);
|
||||||
|
|
||||||
|
return hb;
|
||||||
|
}
|
||||||
|
|
|
@ -131,11 +131,16 @@ const char *uiInit(uiInitOptions *o)
|
||||||
if (registerD2DScratchClass(hDefaultIcon, hDefaultCursor) == 0)
|
if (registerD2DScratchClass(hDefaultIcon, hDefaultCursor) == 0)
|
||||||
return ieLastErr("initializing D2D scratch window class");
|
return ieLastErr("initializing D2D scratch window class");
|
||||||
|
|
||||||
|
hr = uiprivInitImage();
|
||||||
|
if (hr != S_OK)
|
||||||
|
return ieHRESULT("initializing WIC", hr);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiUninit(void)
|
void uiUninit(void)
|
||||||
{
|
{
|
||||||
|
uiprivUninitImage();
|
||||||
uninitMenus();
|
uninitMenus();
|
||||||
unregisterD2DScratchClass();
|
unregisterD2DScratchClass();
|
||||||
unregisterMessageFilter();
|
unregisterMessageFilter();
|
||||||
|
|
|
@ -416,6 +416,8 @@ uiTable *uiNewTable(uiTableModel *model)
|
||||||
t->backgroundColumn = -1;
|
t->backgroundColumn = -1;
|
||||||
|
|
||||||
// TODO update these when the DPI changes
|
// TODO update these when the DPI changes
|
||||||
|
// TODO handle errors
|
||||||
|
// TODO try adding a real transparent image
|
||||||
t->dummyLarge = ImageList_Create(
|
t->dummyLarge = ImageList_Create(
|
||||||
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
|
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
|
||||||
ILC_COLOR32,
|
ILC_COLOR32,
|
||||||
|
|
|
@ -163,3 +163,10 @@ extern D2D1_SIZE_F realGetSize(ID2D1RenderTarget *rt);
|
||||||
|
|
||||||
// draw.cpp
|
// draw.cpp
|
||||||
extern ID2D1DCRenderTarget *makeHDCRenderTarget(HDC dc, RECT *r);
|
extern ID2D1DCRenderTarget *makeHDCRenderTarget(HDC dc, RECT *r);
|
||||||
|
|
||||||
|
// image.cpp
|
||||||
|
extern IWICImagingFactory *uiprivWICFactory;
|
||||||
|
extern HRESULT uiprivInitImage(void);
|
||||||
|
extern void uiprivUninitImage(void);
|
||||||
|
extern IWICBitmap *uiprivImageAppropriateForDC(uiImage *i, HDC dc);
|
||||||
|
extern HBITMAP uiprivWICToGDI(IWICBitmap *b, HDC dc);
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <d2d1.h>
|
#include <d2d1.h>
|
||||||
#include <d2d1helper.h>
|
#include <d2d1helper.h>
|
||||||
#include <dwrite.h>
|
#include <dwrite.h>
|
||||||
|
#include <wincodec.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
Loading…
Reference in New Issue