Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

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
You can’t perform that action at this time.