forked from mia/Aegisub
Mostly rewrite the screen dropper code
Eliminate a lot of the platform-specific code by just using the portable versions everywhere, and use CoreGraphics rather than wxScreenDC to grab an image of the screen on OS X as wxScreenDC doesn't actually work on 10.6+. Originally committed to SVN as r6898.
This commit is contained in:
parent
82d955ba96
commit
2db20778fc
1 changed files with 43 additions and 52 deletions
|
@ -75,6 +75,10 @@
|
|||
#include "persist_location.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __WXMAC__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
/// DOCME
|
||||
/// @class ColorPickerSpectrum
|
||||
/// @brief DOCME
|
||||
|
@ -541,6 +545,7 @@ void ColorPickerRecent::OnSize(wxSizeEvent &)
|
|||
|
||||
ColorPickerScreenDropper::ColorPickerScreenDropper(wxWindow *parent, int resx, int resy, int magnification)
|
||||
: wxControl(parent, -1, wxDefaultPosition, wxDefaultSize, STATIC_BORDER_FLAG)
|
||||
, capture(resx * magnification, resy * magnification)
|
||||
, resx(resx)
|
||||
, resy(resy)
|
||||
, magnification(magnification)
|
||||
|
@ -550,12 +555,10 @@ ColorPickerScreenDropper::ColorPickerScreenDropper(wxWindow *parent, int resx, i
|
|||
SetMaxSize(GetSize());
|
||||
SetCursor(*wxCROSS_CURSOR);
|
||||
|
||||
capture = wxBitmap(resx, resy);
|
||||
wxMemoryDC capdc;
|
||||
capdc.SelectObject(capture);
|
||||
wxMemoryDC capdc(capture);
|
||||
capdc.SetPen(*wxTRANSPARENT_PEN);
|
||||
capdc.SetBrush(*wxWHITE_BRUSH);
|
||||
capdc.DrawRectangle(0, 0, resx, resy);
|
||||
capdc.DrawRectangle(0, 0, capture.GetWidth(), capture.GetHeight());
|
||||
|
||||
Bind(wxEVT_PAINT, &ColorPickerScreenDropper::OnPaint, this);
|
||||
Bind(wxEVT_LEFT_DOWN, &ColorPickerScreenDropper::OnMouse, this);
|
||||
|
@ -565,23 +568,14 @@ wxDEFINE_EVENT(EVT_DROPPER_SELECT, wxCommandEvent);
|
|||
|
||||
void ColorPickerScreenDropper::OnMouse(wxMouseEvent &evt)
|
||||
{
|
||||
int x = evt.GetX() / magnification;
|
||||
int y = evt.GetY() / magnification;
|
||||
int x = evt.GetX();
|
||||
int y = evt.GetY();
|
||||
|
||||
if (x >= 0 && x < capture.GetWidth() && y >= 0 && y < capture.GetHeight()) {
|
||||
wxNativePixelData pd(capture, wxRect(x, y, 1, 1));
|
||||
wxNativePixelData::Iterator pdi(pd.GetPixels());
|
||||
wxColour color(pdi.Red(), pdi.Green(), pdi.Blue(), wxALPHA_OPAQUE);
|
||||
|
||||
if (x >= 0 && y >= 0 && x < resx && y < resy) {
|
||||
wxColour color;
|
||||
#ifdef __WXMAC__
|
||||
// wxMemoryDC::GetPixel() isn't implemented on OS X
|
||||
// Work around it by reading pixel data from the bitmap instead
|
||||
wxAlphaPixelData cappd(capture);
|
||||
wxAlphaPixelData::Iterator cappdi(cappd);
|
||||
cappdi.MoveTo(cappd, x, y);
|
||||
color.Set(cappdi.Red(), cappdi.Green(), cappdi.Blue());
|
||||
#else
|
||||
wxMemoryDC capdc(capture);
|
||||
capdc.GetPixel(x, y, &color);
|
||||
#endif
|
||||
color = wxColour(color.Red(), color.Green(), color.Blue(), wxALPHA_OPAQUE);
|
||||
wxCommandEvent evnt(EVT_DROPPER_SELECT, GetId());
|
||||
evnt.SetString(AssColor(color).GetASSFormatted(false, false, false));
|
||||
AddPendingEvent(evnt);
|
||||
|
@ -590,45 +584,42 @@ void ColorPickerScreenDropper::OnMouse(wxMouseEvent &evt)
|
|||
|
||||
void ColorPickerScreenDropper::OnPaint(wxPaintEvent &)
|
||||
{
|
||||
wxPaintDC pdc(this);
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// See OnMouse() above
|
||||
wxAlphaPixelData cappd(capture);
|
||||
wxAlphaPixelData::Iterator cappdi(cappd);
|
||||
#else
|
||||
wxMemoryDC capdc(capture);
|
||||
#endif
|
||||
|
||||
pdc.SetPen(*wxTRANSPARENT_PEN);
|
||||
|
||||
for (int x = 0; x < resx; x++) {
|
||||
for (int y = 0; y < resy; y++) {
|
||||
wxColour color;
|
||||
#ifdef __WXMAC__
|
||||
cappdi.MoveTo(cappd, x, y);
|
||||
color.Set(cappdi.Red(), cappdi.Green(), cappdi.Blue());
|
||||
#else
|
||||
capdc.GetPixel(x, y, &color);
|
||||
#endif
|
||||
pdc.SetBrush(wxBrush(color));
|
||||
pdc.DrawRectangle(x*magnification, y*magnification, magnification, magnification);
|
||||
}
|
||||
}
|
||||
wxPaintDC(this).DrawBitmap(capture, 0, 0);
|
||||
}
|
||||
|
||||
void ColorPickerScreenDropper::DropFromScreenXY(int x, int y)
|
||||
{
|
||||
wxMemoryDC capdc(capture);
|
||||
capdc.SetPen(*wxTRANSPARENT_PEN);
|
||||
#ifndef __WXMAC__
|
||||
wxScreenDC screen;
|
||||
|
||||
#ifdef __WXMAC__
|
||||
wxBitmap screenbmp = screen.GetAsBitmap().GetSubBitmap(wxRect(x-resx/2, y-resy/2, resx, resy));
|
||||
capdc.DrawBitmap(screenbmp, 0, 0);
|
||||
capdc.StretchBlit(0, 0, resx * magnification, resy * magnification,
|
||||
&screen, x - resx / 2, y - resy / 2, resx, resy);
|
||||
#else
|
||||
screen.StartDrawingOnTop();
|
||||
capdc.Blit(0, 0, resx, resy, &screen, x-resx/2, y-resy/2);
|
||||
screen.EndDrawingOnTop();
|
||||
// wxScreenDC doesn't work on recent versions of OS X so do it manually
|
||||
|
||||
// Doesn't bother handling the case where the rect overlaps two monitors
|
||||
CGDirectDisplayID display_id;
|
||||
uint32_t display_count;
|
||||
CGGetDisplaysWithPoint(CGPointMake(x, y), 1, &display_id, &display_count);
|
||||
|
||||
agi::scoped_holder<CGImageRef> img(CGDisplayCreateImageForRect(display_id, CGRectMake(x - resx / 2, y - resy / 2, resx, resy)), CGImageRelease);
|
||||
NSUInteger width = CGImageGetWidth(img);
|
||||
NSUInteger height = CGImageGetHeight(img);
|
||||
std::vector<uint8_t> imgdata(height * width * 4);
|
||||
|
||||
agi::scoped_holder<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB(), CGColorSpaceRelease);
|
||||
agi::scoped_holder<CGContextRef> bmp_context(CGBitmapContextCreate(&imgdata[0], width, height, 8, 4 * width, colorspace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), CGContextRelease);
|
||||
|
||||
CGContextDrawImage(bmp_context, CGRectMake(0, 0, width, height), img);
|
||||
|
||||
for (int x = 0; x < resx; x++) {
|
||||
for (int y = 0; y < resy; y++) {
|
||||
uint8_t *pixel = &imgdata[y * width * 4 + x * 4];
|
||||
capdc.SetBrush(wxBrush(wxColour(pixel[0], pixel[1], pixel[2])));
|
||||
capdc.DrawRectangle(x * magnification, y * magnification, magnification, magnification);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Refresh(false);
|
||||
|
|
Loading…
Reference in a new issue