Skip to content

Instantly share code, notes, and snippets.

@kylixs
Forked from taxilian/BitBlitter.cpp
Last active August 29, 2015 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kylixs/09e9dcf159ce9fe3ac4c to your computer and use it in GitHub Desktop.
Save kylixs/09e9dcf159ce9fe3ac4c to your computer and use it in GitHub Desktop.
// Platform independent
#include "BitBlitter.h"
#include "precompiled_headers.h" // Anything before this is PCH on windows
bool BitBlitter::onWindowRefresh( FB::RefreshEvent *evt, FB::PluginWindow *win )
{
boost::mutex::scoped_lock _l(preview_mutex);
if (preview_width > 0 && preview_height > 0 && preview_image) {
drawImage(win, evt, preview_image.get(), preview_width, preview_height, preview_gray);
}
return true;
}
void BitBlitter::setPreviewImage( const boost::shared_array<uint8_t>& img, const int width, const int height, bool gray )
{
boost::mutex::scoped_lock _l(preview_mutex);
preview_width = width;
preview_height = height;
preview_image = img;
preview_gray = gray;
}
class BitBlitter : public FB::PluginEventSink
{
public:
BitBlitter() {}
virtual ~BitBlitter() {}
virtual void drawImage(FB::PluginWindow *wnd, FB::PluginEvent* evt, unsigned char *img, int width, int height, bool gray = false) = 0;
virtual void setPreviewImage(const boost::shared_array<uint8_t>& img, const int width, const int height, bool gray = false);
BEGIN_PLUGIN_EVENT_MAP()
EVENTTYPE_CASE(FB::RefreshEvent, onWindowRefresh, FB::PluginWindow)
END_PLUGIN_EVENT_MAP()
virtual bool onWindowRefresh(FB::RefreshEvent *evt, FB::PluginWindow *win);
private:
boost::mutex preview_mutex;
boost::shared_array<uint8_t> preview_image;
int preview_width;
int preview_height;
bool preview_gray;
};
#include "PluginEvents/DrawingEvents.h"
void BitBlitterMac::drawImage(FB::PluginWindow *, FB::PluginEvent* evt, unsigned char *img, int width, int height, bool gray) {
FB::CoreGraphicsDraw* e(static_cast<FB::CoreGraphicsDraw*>(evt));
CGContext* context = e->context;
if(context==NULL) {
printf("Error: no coregraphics context to draw to.\n");
return;
}
int win_width = e->bounds.right - e->bounds.left;
int win_height = e->bounds.bottom - e->bounds.top;
if((width<=1)||(height<=1)) return;
if((width<=1)||(height<=1)) return;
CGContextSaveGState(context);
cf_scoped_ptr<CGColorSpaceRef> colorSpace;
cf_scoped_ptr<CGContextRef> bitmapContext;
if (!gray) {
colorSpace.reset(CGColorSpaceCreateDeviceRGB());
bitmapContext.reset(CGBitmapContextCreate(
img,
width,
height,
8, // bitsPerComponent
4*width, // bytesPerRow
colorSpace,
kCGImageAlphaNoneSkipLast));
} else {
colorSpace.reset(CGColorSpaceCreateDeviceGray());
bitmapContext.reset(CGBitmapContextCreate(
img,
width,
height,
8, // bitsPerComponent
width, // bytesPerRow
colorSpace,
kCGImageAlphaNone));
}
cf_scoped_ptr<CGImageRef> cgImage(CGBitmapContextCreateImage(bitmapContext));
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextTranslateCTM(context, 0, win_height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0, 0, win_width, win_height), cgImage);
CGContextRestoreGState(context);
}
#include "Win/BitBlitterWin.h"
#include "Win/PluginWindowWin.h"
#include "Win/PluginWindowlessWin.h"
void BitBlitterWin::drawImage(FB::PluginWindow *wnd, FB::PluginEvent* evt, unsigned char *img, int width, int height, bool gray) {
HDC hdc=NULL;
BITMAPINFO bitmapInfo;
bitmapInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biBitCount=32;
bitmapInfo.bmiHeader.biCompression=BI_RGB;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biSizeImage = width*height*4;
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
OutputDebugString(L"bitBlt\n");
FB::PluginWindowWin *winwin = dynamic_cast< FB::PluginWindowWin *>(wnd);
if(winwin!=NULL) {
PAINTSTRUCT ps;
hdc = BeginPaint(winwin->getHWND(), &ps);
if(hdc==NULL) return;
int dstWidth = wnd->getWindowWidth();
int dstHeight = wnd->getWindowHeight();
SetStretchBltMode(hdc, HALFTONE);
StretchDIBits(hdc, 0, dstHeight, dstWidth, -dstHeight, 0,0, width, height, img, &bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
EndPaint(winwin->getHWND(), &ps);
}
FB::PluginWindowlessWin *windowlesswin = dynamic_cast< FB::PluginWindowlessWin *>(wnd);
if(windowlesswin!=NULL) {
hdc=windowlesswin->getHDC();
//FB::Rect r = wnd->getWindowPosition(); when we call PluginWindow->InvalidateWindow(), IE's bounds changed every time, we should get it from RefreshEvent
FB::Rect r = evt->bounds;
int dstWidth = wnd->getWindowWidth();
int dstHeight = wnd->getWindowHeight();
SetStretchBltMode(hdc, HALFTONE);
StretchDIBits(hdc, r.left, r.bottom, dstWidth, -dstHeight, 0,0, width, height, img, &bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
if(hdc==NULL) return;
}
OutputDebugString(L"bitBlt end\n");
}
#ifndef BITBLITTERWIN_H
#define BITBLITTERWIN_H
#include "BitBlitter.h"
class BitBlitterWin : public BitBlitter {
virtual void drawImage(FB::PluginWindow *, FB::PluginEvent* evt, unsigned char *img, int width, int height, bool gray = false);
};
#endif
// If you do something like this, you can handle the draw events in your blitter object
Plugin::Plugin() {
// As an example
#ifdef FB_WIN
bitBlitter = new BitBlitterWin();
#endif
#ifdef FB_MACOSX
bitBlitter = new BitBlitterMac();
#endif
}
bool Plugin::onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindow *wnd)
{
FBLOG_INFO("GCPlugin", "Window attached");
wnd->AttachObserver(bitBlitter); // Attach the window to the bitBlitter
return true;
}
bool Plugin::onWindowDetached(FB::DetachedEvent *evt, FB::PluginWindow *wnd)
{
FBLOG_INFO("GCPlugin", "Window detached");
wnd->DetachObserver(bitBlitter); // Detach the window from the bitBlitter
return true;
}
// Note that the bitBlitter will also get attached and detached events when those lines execute.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment