Skip to content

Instantly share code, notes, and snippets.

@taxilian
Last active January 4, 2020 01:53
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save taxilian/1099740 to your computer and use it in GitHub Desktop.
Save taxilian/1099740 to your computer and use it in GitHub Desktop.
Example mac CoreGraphics draw function for FireBreath
// 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();
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.
@kylixs
Copy link

kylixs commented Dec 9, 2014

// BitBlitterWin.cpp
FB::PluginWindowlessWin *windowlesswin = dynamic_cast< FB::PluginWindowlessWin *>(wnd);
if(windowlesswin!=NULL) {
hdc=windowlesswin->getHDC();
FB::Rect r = wnd->getWindowPosition(); // Here is wrong for IE
....
When we call pluginWIndow->InvalidateWindow(), IE 's bounds is changed every time, the right way to get draw bounds is :
FB::Rect r = evt->bounds;
Hope this fix can help someone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment