[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] [SCM] Gnash branch, openvg, updated. 516fc91dd2bbb638ac6a
From: |
Rob Savoye |
Subject: |
[Gnash-commit] [SCM] Gnash branch, openvg, updated. 516fc91dd2bbb638ac6a5e632772f0a0ad9288cc |
Date: |
Sat, 22 Jan 2011 01:04:24 +0000 |
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Gnash".
The branch, openvg has been updated
via 516fc91dd2bbb638ac6a5e632772f0a0ad9288cc (commit)
via 0c41a37f696e34bd1a98bd9cc2ba53f5419c9bfb (commit)
via 0e16b062d6df07b425f4b33f4b60648f1f9cfca4 (commit)
via 6791e5a9dd60c4463955c10ac3060a0a5d931a5b (commit)
via 2b011a109017894358505d78711bff446b9e3fc3 (commit)
via 439d154a5eb8a9c72e58fc15fd18f0de004f8d37 (commit)
via e2337eac41e0802575dc72a0194a4e0ac7a68642 (commit)
from f5244d73f5ca7944b0aa0abf58adbe0faa7a54a2 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit//commit/?id=516fc91dd2bbb638ac6a5e632772f0a0ad9288cc
commit 516fc91dd2bbb638ac6a5e632772f0a0ad9288cc
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 18:04:13 2011 -0700
properly support Linux input events types that use absolute position
reporting. Initize the touchscreen input_absinfo.
diff --git a/libdevice/events/EventDevice.cpp b/libdevice/events/EventDevice.cpp
index 425bbac..509d640 100644
--- a/libdevice/events/EventDevice.cpp
+++ b/libdevice/events/EventDevice.cpp
@@ -181,9 +181,10 @@ EventDevice::init(const std::string &filespec, size_t /*
size */)
// ON the Babbage board, this is the evdev driver version 1.0.0
if (strstr(name, "mxc_ts") != 0) {
log_debug("Babbage Touchscreen found!");
- _type = InputDevice::TOUCHSCREEN;
+ _type = InputDevice::TABLET;
}
if (strstr(name, "mxckpd") != 0) {
+ log_debug("Babbage Power Button found!");
_type = InputDevice::POWERBUTTON;
}
break;
@@ -201,13 +202,33 @@ EventDevice::init(const std::string &filespec, size_t /*
size */)
log_debug("Event enabled for %s on fd #%d", _filespec, _fd);
+ // Set the scale of the display so the absolute postions
+ // we get from the touchscreen driver are correct.
+ struct input_absinfo abs;
+ abs.minimum = 0;
+ abs.fuzz = 4;
+ abs.flat = 8;
+ abs.resolution = 0;
+ abs.maximum = 800;
+ if (ioctl(_fd, EVIOCSABS(ABS_X), &abs) < 0) {
+ perror("ioctl(EVIOCSABS(ABS_X))");
+ }
+ abs.maximum = 480;
+ if (ioctl(_fd, EVIOCSABS(ABS_Y), &abs) < 0) {
+ perror("ioctl(EVIOCSABS(ABS_Y))");
+ }
+#if 0
+ if (ioctl(_fd, EVIOCGRAB, (void *)1) < 0) {
+ perror("ioctl(EVIOCGRAB(1))");
+ }
+#endif
return true;
}
bool
EventDevice::check()
{
- GNASH_REPORT_FUNCTION;
+// GNASH_REPORT_FUNCTION;
bool activity = false;
@@ -221,15 +242,55 @@ EventDevice::check()
if (!buf) {
return false;
}
-
+
+ /// @note
+ /// A typical touchscreen event is actuall a series of events, one for each
+ /// piece of data. The sequence is terminated by the EV_SYN message. An
+ /// example from evtests looks like this:
+ /// Event: time 697585.633672, type 3 (Absolute), code 0 (X), value 127
+ /// Event: time 697585.633679, type 3 (Absolute), code 1 (Y), value 72
+ /// Event: time 697585.633681, type 3 (Absolute), code 24 (Pressure),
value 41
+ /// Event: time 697585.633684, type 1 (Key), code 330 (Touch), value 1
+ /// Event: time 697585.633686, -------------- Report Sync ------------
+ ///
+ /// Everytime we get the EV_SYN message we add this fully populated event
to
+ /// queue of events. As the GUI polls for events, there may be multiple
events
+ /// in the queue by the time the main event loop comes around to process
the
+ /// events.
struct input_event *ev = reinterpret_cast<struct input_event *>(buf.get());
- // log_debug("Type is: %hd, Code is: %hd, Val us: %d", ev->type, ev->code,
- // ev->value);
+ // log_debug("Type is: %hd, Code is: %hd, Val us: %d", ev->type, ev->code,
ev->value);
switch (ev->type) {
case EV_SYN:
- log_unimpl("Sync event from Input Event Device");
+ {
+ boost::shared_ptr<InputDevice::input_data_t> _newdata(new
InputDevice::input_data_t);
+#if 0
+ std::copy(_input_data.begin(), _input_data.end(), _newdata.begin());
+#else
+ _newdata->pressed = _input_data.pressed;
+ _newdata->key = _input_data.key;
+ _newdata->modifier = _input_data.modifier;
+ _newdata->x = _input_data.x;
+ _newdata->y = _input_data.y;
+ _newdata->button = _input_data.button;
+ _newdata->position = _input_data.position;
+ _newdata->pressure = _input_data.pressure;
+ _newdata->volumne = _input_data.volumne;
+ _newdata->distance = _input_data.distance;
+ _newdata->rx = _input_data.rx;
+ _newdata->ry = _input_data.ry;
+ _newdata->rz = _input_data.rz;
+ _newdata->throttle = _input_data.throttle;
+ _newdata->rudder = _input_data.rudder;
+ _newdata->gas = _input_data.gas;
+ _newdata->brake = _input_data.brake;
+ _newdata->tiltX = _input_data.tiltX;
+ _newdata->tiltY = _input_data.tiltY;
+#endif
+ _data.push(_newdata);
+ activity = true;
break;
- // Keyboard event
+ }
+ // Keyboard event
case EV_KEY:
{
// code == scan code of the key (KEY_xxxx defines in input.h)
@@ -248,30 +309,26 @@ EventDevice::check()
keyb_lalt = ev->value;
} else if (ev->code == KEY_RIGHTALT) {
keyb_ralt = ev->value;
+ } else if (ev->code == BTN_TOUCH) {
+ // keyb_ralt = ev->value;
} else {
- gnash::key::code c = scancode_to_gnash_key(ev->code,
- keyb_lshift || keyb_rshift);
+ _input_data.key = scancode_to_gnash_key(ev->code,
+ keyb_lshift ||
keyb_rshift);
// build modifier
- int modifier = gnash::key::GNASH_MOD_NONE;
+ _input_data.modifier = gnash::key::GNASH_MOD_NONE;
if (keyb_lshift || keyb_rshift) {
- modifier = modifier | gnash::key::GNASH_MOD_SHIFT;
+ _input_data.modifier = _input_data.modifier |
gnash::key::GNASH_MOD_SHIFT;
}
if (keyb_lctrl || keyb_rctrl) {
- modifier = modifier | gnash::key::GNASH_MOD_CONTROL;
+ _input_data.modifier = _input_data.modifier |
gnash::key::GNASH_MOD_CONTROL;
}
if (keyb_lalt || keyb_ralt) {
- modifier = modifier | gnash::key::GNASH_MOD_ALT;
- }
-
- // send event
- if (c != gnash::key::INVALID) {
- addData(true, c, modifier, 0, 0);
-// _gui->notify_key_event(c, modifier, ev->value);
- activity = true;
+ _input_data.modifier = _input_data.modifier |
gnash::key::GNASH_MOD_ALT;
}
+ activity = true;
} // if normal key
break;
} // case EV_KEY
@@ -280,9 +337,79 @@ EventDevice::check()
log_unimpl("Relative move event from Input Event Device");
// Touchscreen or joystick
break;
+ // Absolute coordinates come as multiple events, one for
+ // each axis.
case EV_ABS:
- log_unimpl("Absolute move event from Input Event Device");
+ {
+ switch (ev->code) {
+ case ABS_X:
+ // log_debug("ABS_X: %d", ev->value);
+ _input_data.x = ev->value;
+ break;
+ case ABS_Y:
+ {
+ // log_debug("ABS_X: %d ABS_Y: %d", _x, ev->value);
+ _input_data.y = ev->value;
+ }
+ break;
+ // FIXME: Currently the Z axis is ignored
+ case ABS_Z:
+ case ABS_WHEEL:
+ log_debug("ABS_Z: %d", ev->value);
+ break;
+ case ABS_PRESSURE:
+ //log_debug("Pressure: %d", ev->value);
+ _input_data.pressure = ev->value;
+ break;
+ case ABS_VOLUME:
+ log_debug("ABS_VOLUME: %d", ev->value);
+ _input_data.volumne = ev->value;
+ break;
+ case ABS_DISTANCE:
+ log_debug("ABS_DISTANCE: %d", ev->value);
+ _input_data.distance = ev->value;
+ break;
+ case ABS_RX:
+ log_debug("ABS_RX: %d", ev->value);
+ _input_data.rx = ev->value;
+ break;
+ case ABS_RY:
+ log_debug("ABS_RY: %d", ev->value);
+ _input_data.ry = ev->value;
+ break;
+ case ABS_RZ:
+ log_debug("ABS_RZ: %d", ev->value);
+ _input_data.rz = ev->value;
+ break;
+ case ABS_THROTTLE:
+ log_debug("ABS_THROTTLE: %d", ev->value);
+ _input_data.throttle = ev->value;
+ break;
+ case ABS_RUDDER:
+ log_debug("ABS_RUDDER: %d", ev->value);
+ _input_data.rudder = ev->value;
+ break;
+ case ABS_GAS:
+ log_debug("ABS_GAS: %d", ev->value);
+ _input_data.gas = ev->value;
+ break;
+ case ABS_BRAKE:
+ log_debug("ABS_BRAKE: %d", ev->value);
+ _input_data.brake = ev->value;
+ break;
+ case ABS_TILT_X:
+ log_debug("ABS_TILT_X: %d", ev->value);
+ _input_data.tiltX = ev->value;
+ break;
+ case ABS_TILT_Y:
+ log_debug("ABS_TILT_Y: %d", ev->value);
+ _input_data.tiltY = ev->value;
+ break;
+ default:
+ break;
+ }
break;
+ }
case EV_MSC:
log_unimpl("Misc event from Input Event Device");
break;
@@ -423,7 +550,6 @@ EventDevice::scancode_to_gnash_key(int code, bool shift)
case KEY_DELETE : return gnash::key::DELETEKEY;
case KEY_HOME : return gnash::key::HOME;
case KEY_END : return gnash::key::END;
-
}
return gnash::key::INVALID;
@@ -433,7 +559,7 @@ EventDevice::scancode_to_gnash_key(int code, bool shift)
std::vector<boost::shared_ptr<InputDevice> >
EventDevice::scanForDevices()
{
- // GNASH_REPORT_FUNCTION;
+ GNASH_REPORT_FUNCTION;
struct stat st;
@@ -483,15 +609,9 @@ EventDevice::scanForDevices()
close(fd);
boost::shared_ptr<InputDevice> dev;
dev = boost::shared_ptr<InputDevice>(new EventDevice());
- // For now we only want keyboards, as the mouse interface
- // default of /dev/input/mice supports hotpluging devices,
- // unlike the regular event.
if (dev->init(filespec, DEFAULT_BUFFER_SIZE)) {
- if ((dev->getType() == InputDevice::KEYBOARD)) {
- devices.push_back(dev);
- }
+ devices.push_back(dev);
}
-
// dev->dump();
// setup the next device filespec to try
diff --git a/libdevice/events/MouseDevice.cpp b/libdevice/events/MouseDevice.cpp
index af38ea6..741adcf 100644
--- a/libdevice/events/MouseDevice.cpp
+++ b/libdevice/events/MouseDevice.cpp
@@ -286,36 +286,36 @@ MouseDevice::check()
log_debug(_("x/y %d/%d button %d"), xmove, ymove, btn);
// movement
- _x += xmove;
- _y += ymove;
+ _input_data.x += xmove;
+ _input_data.y += ymove;
- if (_x < 0) {
- _x = 0;
+ if (_input_data.x < 0) {
+ _input_data.x = 0;
}
- if (_y < 0) {
- _y = 0;
+ if (_input_data.y < 0) {
+ _input_data.y = 0;
}
// FIXME: this is a bit of a temporary hack. The last two
// arguments are a range, so hardcoding them is safe for
// now. In the future more conversion may be done, making this
// then be incorrect.
boost::shared_array<int> coords =
- MouseDevice::convertCoordinates(_x, _y, 1024, 768);
+ MouseDevice::convertCoordinates(_input_data.x, _input_data.y,
1024, 768);
// MouseDevice::convertCoordinates(_x, _y,
// _gui->getStage()->getStageWidth(),
// _gui->getStage()->getStageHeight());
- _x = coords[0];
- _y = coords[1];
+ _input_data.x = coords[0];
+ _input_data.y = coords[1];
} // end of InputDevice::MOUSE
- log_debug(_("read mouse @ %d / %d, btn %d"), _x, _y, _button);
- addData(false, gnash::key::INVALID, 0, _x, _y);
+ log_debug(_("read mouse @ %d / %d, btn %d"), _input_data.x, _input_data.y,
_input_data.button);
+ addData(false, gnash::key::INVALID, 0, _input_data.x, _input_data.y);
// button
- if (btn != _button) {
- _button = btn;
+ if (btn != _input_data.button) {
+ _input_data.button = btn;
log_debug("clicked: %d", btn);
- addData(true, gnash::key::INVALID, 0, _x, _y);
+ addData(true, gnash::key::INVALID, 0, _input_data.x, _input_data.y);
log_debug(_("mouse click! %d"), btn);
}
@@ -363,7 +363,7 @@ MouseDevice::command(unsigned char cmd, unsigned char *buf,
int count)
boost::shared_array<int>
MouseDevice::convertCoordinates(int x, int y, int width, int height)
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
boost::shared_array<int> coords(new int[2]);
diff --git a/libdevice/events/TouchDevice.cpp b/libdevice/events/TouchDevice.cpp
index 5a5fbfd..2063071 100644
--- a/libdevice/events/TouchDevice.cpp
+++ b/libdevice/events/TouchDevice.cpp
@@ -98,6 +98,8 @@ TouchDevice::init(const std::string &filespec, size_t /* size
*/)
return false;
}
+ _fd = ts_fd(_tsDev);
+
log_debug("Using TSLIB on %s", devname);
return true;
}
@@ -283,7 +285,16 @@ TouchDevice::scanForDevices()
// Debug strings to make output more readable
const char *debug[] = {
- "TSlib"
+ "UNKNOWN",
+ "KEYBOARD",
+ "MOUSE",
+ "TABLET",
+ "TOUCHSCREEN",
+ "TOUCHMOUSE",
+ "POWERBUTTON",
+ "SLEEPBUTTON",
+ "SERIALUSB",
+ "INFRARED"
};
// Look for these files for mouse input
@@ -301,6 +312,7 @@ TouchDevice::scanForDevices()
int i = 0;
while (touch[i].type != InputDevice::UNKNOWN) {
int fd = 0;
+ // log_debug("Checking for device %s...", touch[i].filespec);
if (stat(touch[i].filespec, &st) == 0) {
// Then see if we can open it
if ((fd = open(touch[i].filespec, O_RDWR)) < 0) {
@@ -309,18 +321,17 @@ TouchDevice::scanForDevices()
i++;
continue;
} // open()
- log_debug("Found a %s device for mouse input using %s",
+ close(fd);
+ log_debug("Found a %s device for touchscreen input using %s",
debug[touch[i].type], touch[i].filespec);
boost::shared_ptr<InputDevice> dev;
dev = boost::shared_ptr<InputDevice>(new TouchDevice());
if (dev->init(touch[i].filespec, DEFAULT_BUFFER_SIZE)) {
devices.push_back(dev);
+ break;
}
- dev->dump();
-
- devices.push_back(dev);
+// dev->dump();
} // stat()
- close(fd);
i++;
} // while()
diff --git a/libdevice/events/events.am b/libdevice/events/events.am
index b4bd0c0..1808a06 100644
--- a/libdevice/events/events.am
+++ b/libdevice/events/events.am
@@ -41,7 +41,7 @@ endif
endif
if ENABLE_DEVELOPER_TESTS
-check_PROGRAMS += test_events
+check_PROGRAMS += test_events evtest
test_events_SOURCES = events/test_events.cpp
test_events_CPPFLAGS = $(AM_CPPFLAGS)
test_events_LDADD = \
@@ -51,4 +51,12 @@ test_events_LDADD = \
$(CURL_LIBS) \
$(EVENTS_LIBS) \
$(GNASH_LIBS)
+
+evtest_SOURCES = events/evtest.c
+evtest_CPPFLAGS = $(AM_CPPFLAGS)
+evtest_LDADD = \
+ $(EXTRA_EVENTS_LIBS) \
+ $(TS_LIBS) \
+ $(EVENTS_LIBS) \
+ $(GNASH_LIBS)
endif
\ No newline at end of file
diff --git a/libdevice/events/test_events.cpp b/libdevice/events/test_events.cpp
index 342a822..6779eb4 100644
--- a/libdevice/events/test_events.cpp
+++ b/libdevice/events/test_events.cpp
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
if (id->check()) {
// FIXME: process the input data
boost::shared_ptr<InputDevice::input_data_t> ie =
id->popData();
-#if 1
+#if 0
if (ie) {
cerr << "Got data: " << ie->pressed;
cerr << ", " << ie->key << ", " << ie->modifier;
@@ -113,10 +113,10 @@ main(int argc, char *argv[])
cerr << "X = " << coords[0] << endl;
cerr << "Y = " << coords[1] << endl;
}
+#endif
} else {
std::cerr << ".";
}
-#endif
}
// wait the "heartbeat" interval. The default mouse update rate is
http://git.savannah.gnu.org/cgit//commit/?id=0c41a37f696e34bd1a98bd9cc2ba53f5419c9bfb
commit 0c41a37f696e34bd1a98bd9cc2ba53f5419c9bfb
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 18:01:55 2011 -0700
add more event types
diff --git a/libdevice/events/InputDevice.cpp b/libdevice/events/InputDevice.cpp
index e5902fb..73a949b 100644
--- a/libdevice/events/InputDevice.cpp
+++ b/libdevice/events/InputDevice.cpp
@@ -28,13 +28,10 @@ namespace gnash {
InputDevice::InputDevice()
: _type(InputDevice::UNKNOWN),
- _fd(-1),
- _x(0),
- _y(0),
- _button(0),
- _position(0)
+ _fd(-1)
{
// GNASH_REPORT_FUNCTION;
+ memset(&_input_data, 0, sizeof(InputDevice::input_data_t));
}
InputDevice::~InputDevice()
@@ -92,7 +89,7 @@ InputDevice::popData()
void
InputDevice::addData(bool pressed, key::code key, int modifier, int x, int y)
{
- GNASH_REPORT_FUNCTION;
+ // GNASH_REPORT_FUNCTION;
boost::shared_ptr<input_data_t> _newdata(new input_data_t);
_newdata->pressed = pressed;
@@ -132,7 +129,7 @@ InputDevice::readData(size_t size)
// log_debug ("The pipe for fd #%d timed out waiting to read", fd);
return inbuf;
} else if (ret == 1) {
- log_debug ("The device for fd #%d is ready", _fd);
+ // log_debug ("The device for fd #%d is ready", _fd);
} else {
log_error("The device has this error: %s", strerror(errno));
return inbuf;
@@ -141,7 +138,7 @@ InputDevice::readData(size_t size)
inbuf.reset(new boost::uint8_t[size]);
ret = ::read(_fd, inbuf.get(), size);
if (ret > 0) {
- log_debug("Read %d bytes, %s", ret, hexify(inbuf.get(), ret, false));
+ // log_debug("Read %d bytes, %s", ret, hexify(inbuf.get(), ret,
false));
} else {
inbuf.reset();
}
@@ -157,6 +154,7 @@ InputDevice::dump()
"UNKNOWN",
"Keyboard",
"Mouse",
+ "Tablet",
"Touchscreen",
"Touchscreen Mouse",
"Power Button",
@@ -204,6 +202,22 @@ InputDevice::scanForDevices()
return devices;
}
+// The Babbage touchscreen gives is absolute coordinates, but they don't
+// match the actual screen resolution. So we convert the coordinates
+// to a new absolute location.
+// For example, if the LCD is 480 x 800, the tablet thinks this is 1010 x 960.
+// This should really use a calibration function, but as we know the numbers...
+boost::shared_array<int>
+InputDevice::convertAbsCoords(int x, int y, int width, int height)
+{
+ boost::shared_array<int> coords(new int[2]);
+
+ coords[0] = (x/width) * x;
+ coords[1] = (y/height) * y;
+
+ return coords;
+}
+
// end of gnash namespace
}
http://git.savannah.gnu.org/cgit//commit/?id=0e16b062d6df07b425f4b33f4b60648f1f9cfca4
commit 0e16b062d6df07b425f4b33f4b60648f1f9cfca4
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 18:01:29 2011 -0700
libdevice/events/InputDevice.cpp
diff --git a/libdevice/events/InputDevice.h b/libdevice/events/InputDevice.h
index ddc0c84..9245e34 100644
--- a/libdevice/events/InputDevice.h
+++ b/libdevice/events/InputDevice.h
@@ -36,7 +36,7 @@
namespace gnash {
// Define if you want to support multiple input devices of the same type.
-// The default is to support the devices we prefer for moluse, keyboard,
+// The default is to support the devices we prefer for mouse, keyboard,
// and touchscreen.
// #define MULTIPLE_DEVICES 1
@@ -55,11 +55,26 @@ public:
int modifier;
int x;
int y;
+ int button;
+ int position;
+ int pressure;
+ int volumne;
+ int distance;
+ int rx;
+ int ry;
+ int rz;
+ int throttle;
+ int rudder;
+ int gas;
+ int brake;
+ int tiltX;
+ int tiltY;
} input_data_t;
typedef enum {
UNKNOWN,
KEYBOARD,
MOUSE,
+ TABLET,
TOUCHSCREEN,
TOUCHMOUSE,
POWERBUTTON,
@@ -86,9 +101,11 @@ public:
// Read data into the Device input buffer.
boost::shared_array<boost::uint8_t> readData(size_t size);
-
boost::shared_ptr<input_data_t> popData();
-
+
+ static boost::shared_array<int> convertAbsCoords(int x, int y,
+ int width, int height);
+
void dump();
protected:
void addData(bool pressed, key::code key, int modifier, int x, int y);
@@ -96,11 +113,8 @@ protected:
devicetype_e _type;
std::string _filespec;
int _fd;
- int _x;
- int _y;
- // Touchscreens don't have buttons
- int _button;
- size_t _position;
+ input_data_t _input_data;
+ // These hold the data queue
boost::scoped_array<boost::uint8_t> _buffer;
std::queue<boost::shared_ptr<input_data_t> > _data;
};
http://git.savannah.gnu.org/cgit//commit/?id=6791e5a9dd60c4463955c10ac3060a0a5d931a5b
commit 6791e5a9dd60c4463955c10ac3060a0a5d931a5b
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 17:44:37 2011 -0700
only minor reformatting changes
diff --git a/librender/agg/Renderer_agg.cpp b/librender/agg/Renderer_agg.cpp
index a245617..a0cbb88 100644
--- a/librender/agg/Renderer_agg.cpp
+++ b/librender/agg/Renderer_agg.cpp
@@ -209,8 +209,7 @@ analyzePaths(const GnashPaths &paths, bool& have_shape,
const int pcount = paths.size();
- for (int pno=0; pno<pcount; ++pno) {
-
+ for (int pno=0; pno<pcount; ++pno) {
const Path &the_path = paths[pno];
if ((the_path.m_fill0 > 0) || (the_path.m_fill1 > 0)) {
@@ -233,7 +232,7 @@ public:
:
_path(path),
_shift(shift)
- {}
+ { }
void operator()(const Edge& edge)
{
@@ -264,8 +263,7 @@ public:
_dest(dest),
_it(_dest.begin()),
_shift(shift)
- {
- }
+ { }
void operator()(const Path& in)
{
@@ -457,7 +455,7 @@ public:
EmptyVideoRenderer(const ClipBounds& clipbounds)
:
_clipbounds(clipbounds)
- {}
+ { }
void render(agg::path_storage& path, Renderer& rbase,
const AlphaMasks& masks)
@@ -466,8 +464,7 @@ public:
// No mask active
agg::scanline_p8 sl;
renderScanlines(path, rbase, sl);
- }
- else {
+ } else {
// Untested.
typedef agg::scanline_u8_am<agg::alpha_mask_gray8> Scanline;
Scanline sl(masks.back()->getMask());
@@ -485,8 +482,7 @@ private:
agg::renderer_scanline_aa_solid<Renderer> ren_sl(rbase);
for (ClipBounds::const_iterator i = _clipbounds.begin(),
- e = _clipbounds.end(); i != e; ++i)
- {
+ e = _clipbounds.end(); i != e; ++i) {
const ClipBounds::value_type& cb = *i;
applyClipBox<Rasterizer>(ras, cb);
ras.add_path(path);
@@ -584,20 +580,19 @@ public:
void render(agg::path_storage& path, Renderer& rbase,
const AlphaMasks& masks)
{
- switch (_quality)
- {
- case QUALITY_BEST:
- case QUALITY_HIGH:
- if (_smoothing) {
- renderFrame<HighQualityFilter>(path, rbase, masks);
- }
- else renderFrame<LowQualityFilter>(path, rbase, masks);
- break;
- case QUALITY_MEDIUM:
- case QUALITY_LOW:
- // FIXME: Should this be still lower quality?
- renderFrame<LowQualityFilter>(path, rbase, masks);
- break;
+ switch (_quality) {
+ case QUALITY_BEST:
+ case QUALITY_HIGH:
+ if (_smoothing) {
+ renderFrame<HighQualityFilter>(path, rbase, masks);
+ }
+ else renderFrame<LowQualityFilter>(path, rbase, masks);
+ break;
+ case QUALITY_MEDIUM:
+ case QUALITY_LOW:
+ // FIXME: Should this be still lower quality?
+ renderFrame<LowQualityFilter>(path, rbase, masks);
+ break;
}
}
@@ -613,8 +608,7 @@ private:
// No mask active
agg::scanline_u8 sl;
renderScanlines(path, rbase, sl, sg);
- }
- else {
+ } else {
// Untested.
typedef agg::scanline_u8_am<agg::alpha_mask_gray8> Scanline;
Scanline sl(masks.back()->getMask());
@@ -628,13 +622,11 @@ private:
{
Rasterizer _ras;
for (ClipBounds::const_iterator i = _clipbounds.begin(),
- e = _clipbounds.end(); i != e; ++i)
- {
+ e = _clipbounds.end(); i != e; ++i) {
const ClipBounds::value_type& cb = *i;
applyClipBox<Rasterizer> (_ras, cb);
-
+
_ras.add_path(path);
-
agg::render_scanlines_aa(_ras, sl, rbase, _sa, sg);
}
}
@@ -685,14 +677,12 @@ public:
// bitmap fill style.
gnash::CachedBitmap* createCachedBitmap(std::auto_ptr<image::GnashImage>
im)
{
- GNASH_REPORT_FUNCTION;
return new agg_bitmap_info(im);
}
virtual void renderToImage(boost::shared_ptr<IOChannel> io,
FileType type, int quality) const
{
- GNASH_REPORT_FUNCTION;
image::ImageRGBA im(xres, yres);
for (int x = 0; x < xres; ++x) {
for (int y = 0; y < yres; ++y) {
@@ -785,95 +775,89 @@ public:
}
#endif
- switch (frame->type())
- {
- case image::TYPE_RGBA:
- renderVideo<agg::pixfmt_rgba32_pre>(*frame, mtx, path, smooth);
- break;
- case image::TYPE_RGB:
- renderVideo<agg::pixfmt_rgb24_pre>(*frame, mtx, path, smooth);
- break;
- default:
- log_error("Can't render this type of frame");
- break;
+ switch (frame->type()) {
+ case image::TYPE_RGBA:
+ renderVideo<agg::pixfmt_rgba32_pre>(*frame, mtx, path, smooth);
+ break;
+ case image::TYPE_RGB:
+ renderVideo<agg::pixfmt_rgb24_pre>(*frame, mtx, path, smooth);
+ break;
+ default:
+ log_error("Can't render this type of frame");
+ break;
}
-
}
// Constructor
- Renderer_agg(int bits_per_pixel)
- :
- xres(1),
- yres(1),
- bpp(bits_per_pixel),
- scale_set(false),
- m_display_width(0.0),
- m_display_height(0.0),
- m_drawing_mask(false)
- {
- // TODO: we really don't want to set the scale here as the core should
- // tell us the right values before rendering anything. However this is
- // currently difficult to implement. Removing the next call will
- // lead to an assertion failure in begin_display() because we check
- // whether the scale is known there.
- set_scale(1.0f, 1.0f);
- }
-
- /// Initializes the rendering buffer. The memory pointed by "mem" is not
- /// owned by the renderer and init_buffer() may be called multiple times
- /// when the buffer size changes, for example. However, bits_per_pixel must
- /// remain the same.
- /// rowstride is the size, in bytes, of one row.
- /// This method *must* be called prior to any other method of the class!
+ Renderer_agg(int bits_per_pixel)
+ :
+ xres(1),
+ yres(1),
+ bpp(bits_per_pixel),
+ scale_set(false),
+ m_display_width(0.0),
+ m_display_height(0.0),
+ m_drawing_mask(false)
+ {
+ // TODO: we really don't want to set the scale here as the core
should
+ // tell us the right values before rendering anything. However this
is
+ // currently difficult to implement. Removing the next call will
+ // lead to an assertion failure in begin_display() because we check
+ // whether the scale is known there.
+ set_scale(1.0f, 1.0f);
+ }
+
+ /// Initializes the rendering buffer. The memory pointed by "mem" is not
+ /// owned by the renderer and init_buffer() may be called multiple times
+ /// when the buffer size changes, for example. However, bits_per_pixel must
+ /// remain the same.
+ /// rowstride is the size, in bytes, of one row.
+ /// This method *must* be called prior to any other method of the class!
void init_buffer(unsigned char *mem, int /* size */, int x, int y, int
rowstride)
- {
- GNASH_REPORT_FUNCTION;
- assert(x > 0);
- assert(y > 0);
-
- xres = x;
- yres = y;
-
- m_rbuf.attach(mem, xres, yres, rowstride);
-
- // allocate pixel format accessor and renderer_base
- m_pixf.reset(new PixelFormat(m_rbuf));
- m_rbase.reset(new renderer_base(*m_pixf));
-
- // by default allow drawing everywhere
- set_invalidated_region_world();
- }
-
-
- void begin_display(const gnash::rgba& bg,
- int /*viewport_width*/, int /*viewport_height*/,
- float /*x0*/, float /*x1*/, float /*y0*/, float /*y1*/)
- {
- GNASH_REPORT_FUNCTION;
- assert(m_pixf.get());
-
- assert(scale_set);
-
- // Render images list is cleared here because the GUI may want
- // them for display after ::end_display()
- _render_images.clear();
-
- // clear the stage using the background color
- if ( ! _clipbounds.empty() ) {
- const agg::rgba8& col = agg::rgba8_pre(bg.m_r, bg.m_g, bg.m_b, bg.m_a);
- for (ClipBounds::const_iterator i = _clipbounds.begin(),
- e = _clipbounds.end(); i!= e; ++i) {
- clear_framebuffer(*i, col);
+ {
+ assert(x > 0);
+ assert(y > 0);
+
+ xres = x;
+ yres = y;
+
+ m_rbuf.attach(mem, xres, yres, rowstride);
+
+ // allocate pixel format accessor and renderer_base
+ m_pixf.reset(new PixelFormat(m_rbuf));
+ m_rbase.reset(new renderer_base(*m_pixf));
+
+ // by default allow drawing everywhere
+ set_invalidated_region_world();
}
- }
- // reset status variables
- m_drawing_mask = false;
- }
-
- virtual Renderer* startInternalRender(image::GnashImage& im) {
- GNASH_REPORT_FUNCTION;
+ void begin_display(const gnash::rgba& bg,
+ int /*viewport_width*/, int /*viewport_height*/,
+ float /*x0*/, float /*x1*/, float /*y0*/, float /*y1*/)
+ {
+ assert(m_pixf.get());
+
+ assert(scale_set);
+
+ // Render images list is cleared here because the GUI may want
+ // them for display after ::end_display()
+ _render_images.clear();
+
+ // clear the stage using the background color
+ if ( ! _clipbounds.empty() ) {
+ const agg::rgba8& col = agg::rgba8_pre(bg.m_r, bg.m_g, bg.m_b,
bg.m_a);
+ for (ClipBounds::const_iterator i = _clipbounds.begin(),
+ e = _clipbounds.end(); i!= e; ++i) {
+ clear_framebuffer(*i, col);
+ }
+ }
+
+ // reset status variables
+ m_drawing_mask = false;
+ }
+ virtual Renderer* startInternalRender(image::GnashImage& im)
+ {
std::auto_ptr<Renderer_agg_base> in;
switch (im.type()) {
@@ -897,7 +881,6 @@ public:
}
virtual void endInternalRender() {
- GNASH_REPORT_FUNCTION;
_external.reset();
}
@@ -909,8 +892,6 @@ public:
void clear_framebuffer(const geometry::Range2d<int>& region,
const agg::rgba8& color)
{
- GNASH_REPORT_FUNCTION;
-
assert(region.isFinite());
// add 1 to width since we have still to draw a pixel when
@@ -933,8 +914,6 @@ public:
// Clean up after rendering a frame.
void end_display()
{
- GNASH_REPORT_FUNCTION;
-
if (m_drawing_mask) {
log_debug(_("Warning: rendering ended while drawing a mask"));
}
@@ -950,8 +929,6 @@ public:
void drawLine(const std::vector<point>& coords, const rgba& color,
const SWFMatrix& line_mat)
{
- GNASH_REPORT_FUNCTION;
-
assert(m_pixf.get());
if (_clipbounds.empty()) return;
@@ -974,7 +951,6 @@ public:
// We've asserted that it has at least one element.
Points::const_iterator i = coords.begin();
-
point pnt;
mat.transform(&pnt, *i);
@@ -982,26 +958,22 @@ public:
++i;
- for (const Points::const_iterator e = coords.end(); i != e; ++i)
- {
+ for (const Points::const_iterator e = coords.end(); i != e; ++i) {
mat.transform(&pnt, *i);
path.line_to(pnt.x, pnt.y);
}
-
+
if (_alphaMasks.empty()) {
// No mask active
agg::scanline_p8 sl;
lr.render(sl, stroke, color);
- }
- else {
+ } else {
// Mask is active!
typedef agg::scanline_u8_am<agg::alpha_mask_gray8> sl_type;
sl_type sl(_alphaMasks.back()->getMask());
lr.render(sl, stroke, color);
}
-
- }
-
+ }
void begin_submit_mask()
{
@@ -1011,126 +983,121 @@ public:
AlphaMask* new_mask = new AlphaMask(xres, yres);
for (ClipBounds::const_iterator i = _clipbounds.begin(),
- e = _clipbounds.end(); i != e; ++i) {
+ e = _clipbounds.end(); i != e; ++i) {
new_mask->clear(*i);
}
-
+
_alphaMasks.push_back(new_mask);
}
-
- void end_submit_mask()
- {
- m_drawing_mask = false;
- }
-
- void disable_mask()
- {
- assert( ! _alphaMasks.empty() );
- delete _alphaMasks.back();
- _alphaMasks.pop_back();
- }
-
-
- void drawGlyph(const SWF::ShapeRecord& shape, const rgba& color,
- const SWFMatrix& mat)
- {
- GNASH_REPORT_FUNCTION;
- // select relevant clipping bounds
- if (shape.getBounds().is_null()) {
- return;
- }
- select_clipbounds(shape.getBounds(), mat);
-
- if (_clipbounds_selected.empty()) return;
-
- GnashPaths paths;
- apply_matrix_to_path(shape.paths(), paths, mat);
-
- // If it's a mask, we don't need the rest.
- if (m_drawing_mask) {
- draw_mask_shape(paths, false);
- return;
- }
-
- // convert gnash paths to agg paths.
- AggPaths agg_paths;
- buildPaths(agg_paths, paths);
-
- std::vector<FillStyle> v(1, FillStyle(SolidFill(color)));
-
- // prepare style handler
- StyleHandler sh;
- build_agg_styles(sh, v, mat, SWFCxForm());
-
- draw_shape(-1, paths, agg_paths, sh, false);
+ void end_submit_mask()
+ {
+ m_drawing_mask = false;
+ }
- // NOTE: Do not use even-odd filling rule for glyphs!
+ void disable_mask()
+ {
+ assert( ! _alphaMasks.empty() );
+ delete _alphaMasks.back();
+ _alphaMasks.pop_back();
+ }
- // clear clipping ranges to ease debugging
- _clipbounds_selected.clear();
- }
-
-
- /// Fills _clipbounds_selected with pointers to _clipbounds members who
- /// intersect with the given character (transformed by mat). This avoids
- /// rendering of characters outside a particular clipping range.
- /// "_clipbounds_selected" is used by draw_shape() and draw_outline() and
- /// *must* be initialized prior to using those function.
- void select_clipbounds(const SWFRect& objectBounds, const SWFMatrix&
source_mat)
- {
- SWFMatrix mat = stage_matrix;
- mat.concatenate(source_mat);
-
- _clipbounds_selected.clear();
- _clipbounds_selected.reserve(_clipbounds.size());
-
- if (objectBounds.is_null()) {
- log_debug(_("Warning: select_clipbounds encountered a character "
- "definition with null bounds"));
- return;
- }
-
- SWFRect bounds;
- bounds.set_null();
- bounds.expand_to_transformed_rect(mat, objectBounds);
+ void drawGlyph(const SWF::ShapeRecord& shape, const rgba& color,
+ const SWFMatrix& mat)
+ {
+ // select relevant clipping bounds
+ if (shape.getBounds().is_null()) {
+ return;
+ }
+ select_clipbounds(shape.getBounds(), mat);
+
+ if (_clipbounds_selected.empty()) return;
+
+ GnashPaths paths;
+ apply_matrix_to_path(shape.paths(), paths, mat);
+
+ // If it's a mask, we don't need the rest.
+ if (m_drawing_mask) {
+ draw_mask_shape(paths, false);
+ return;
+ }
+
+ // convert gnash paths to agg paths.
+ AggPaths agg_paths;
+ buildPaths(agg_paths, paths);
+
+ std::vector<FillStyle> v(1, FillStyle(SolidFill(color)));
+
+ // prepare style handler
+ StyleHandler sh;
+ build_agg_styles(sh, v, mat, SWFCxForm());
+
+ draw_shape(-1, paths, agg_paths, sh, false);
+
+ // NOTE: Do not use even-odd filling rule for glyphs!
+
+ // clear clipping ranges to ease debugging
+ _clipbounds_selected.clear();
+ }
- assert(bounds.getRange().isFinite());
- const int count = _clipbounds.size();
- for (int cno=0; cno<count; ++cno) {
-
- if (_clipbounds[cno].intersects(bounds.getRange()))
- _clipbounds_selected.push_back(&_clipbounds[cno]);
-
- }
- }
-
- void select_all_clipbounds() {
-
- if (_clipbounds_selected.size() == _clipbounds.size()) return;
-
- _clipbounds_selected.clear();
- _clipbounds_selected.reserve(_clipbounds.size());
+ /// Fills _clipbounds_selected with pointers to _clipbounds members who
+ /// intersect with the given character (transformed by mat). This avoids
+ /// rendering of characters outside a particular clipping range.
+ /// "_clipbounds_selected" is used by draw_shape() and draw_outline() and
+ /// *must* be initialized prior to using those function.
+ void select_clipbounds(const SWFRect& objectBounds, const SWFMatrix&
source_mat)
+ {
+
+ SWFMatrix mat = stage_matrix;
+ mat.concatenate(source_mat);
+
+ _clipbounds_selected.clear();
+ _clipbounds_selected.reserve(_clipbounds.size());
+
+ if (objectBounds.is_null()) {
+ log_debug(_("Warning: select_clipbounds encountered a character
"
+ "definition with null bounds"));
+ return;
+ }
+
+ SWFRect bounds;
+ bounds.set_null();
+ bounds.expand_to_transformed_rect(mat, objectBounds);
+
+ assert(bounds.getRange().isFinite());
+
+ const int count = _clipbounds.size();
+ for (int cno=0; cno<count; ++cno) {
+
+ if (_clipbounds[cno].intersects(bounds.getRange()))
+ _clipbounds_selected.push_back(&_clipbounds[cno]);
+
+ }
+ }
- for (ClipBounds::iterator i = _clipbounds.begin(),
- e = _clipbounds.end(); i != e; ++i)
- {
- _clipbounds_selected.push_back(&(*i));
+ void select_all_clipbounds() {
+
+ if (_clipbounds_selected.size() == _clipbounds.size()) return;
+
+ _clipbounds_selected.clear();
+ _clipbounds_selected.reserve(_clipbounds.size());
+
+ for (ClipBounds::iterator i = _clipbounds.begin(),
+ e = _clipbounds.end(); i != e; ++i) {
+ _clipbounds_selected.push_back(&(*i));
+ }
}
- }
-
+
void drawShape(const SWF::ShapeRecord& shape, const Transform& xform)
{
- GNASH_REPORT_FUNCTION;
// check if the character needs to be rendered at all
SWFRect cur_bounds;
cur_bounds.expand_to_transformed_rect(xform.matrix, shape.getBounds());
- if (!Renderer::bounds_in_clipping_area(cur_bounds))
- {
+ if (!Renderer::bounds_in_clipping_area(cur_bounds)) {
return; // no need to draw
}
@@ -1151,8 +1118,6 @@ public:
const std::vector<Path>& objpaths, const SWFMatrix& mat,
const SWFCxForm& cx)
{
- GNASH_REPORT_FUNCTION;
-
bool have_shape, have_outline;
analyzePaths(objpaths, have_shape, have_outline);
@@ -1168,7 +1133,6 @@ public:
// Masks apparently do not use agg_paths, so return
// early
if (m_drawing_mask) {
-
// Shape is drawn inside a mask, skip sub-shapes handling and
// outlines
draw_mask_shape(paths, false);
@@ -1203,8 +1167,7 @@ public:
// We need to separate sub-shapes during rendering.
const unsigned int subshape_count = count_sub_shapes(paths);
- for (unsigned int subshape=0; subshape<subshape_count; ++subshape)
- {
+ for (unsigned int subshape=0; subshape<subshape_count; ++subshape) {
if (have_shape) {
draw_shape(subshape, paths, agg_paths, sh, true);
}
@@ -1240,830 +1203,801 @@ public:
}
- /// A shape can have sub-shapes. This can happen when there are multiple
- /// layers of the same frame count. Flash combines them to one single shape.
- /// The problem with sub-shapes is, that outlines can be hidden by other
- /// layers so they must be rendered separately.
- unsigned int count_sub_shapes(const GnashPaths &path_in)
- {
- unsigned int sscount=1;
- const size_t pcnt = path_in.size();
-
- for (size_t pno=0; pno<pcnt; ++pno) {
- const Path& this_path = path_in[pno];
-
- if (this_path.m_new_shape)
- sscount++;
- }
+ /// A shape can have sub-shapes. This can happen when there are multiple
+ /// layers of the same frame count. Flash combines them to one single
shape.
+ /// The problem with sub-shapes is, that outlines can be hidden by other
+ /// layers so they must be rendered separately.
+ unsigned int count_sub_shapes(const GnashPaths &path_in)
+ {
+ unsigned int sscount=1;
+ const size_t pcnt = path_in.size();
+
+ for (size_t pno=0; pno<pcnt; ++pno) {
+ const Path& this_path = path_in[pno];
+
+ if (this_path.m_new_shape)
+ sscount++;
+ }
+
+ return sscount;
+ }
- return sscount;
- }
-
- // Version of buildPaths that uses rounded coordinates (pixel hinting)
- // for line styles that want it.
- // This is used for outlines which are aligned to the pixel grid to avoid
- // anti-aliasing problems (a perfect horizontal line being drawn over two
- // lines and looking blurry). The proprietary player does this too.
- //
- // Not all points are aligned, only those lines that:
- // - are straight
- // - are pure horizontal or vertical
- // Also, single segments of a path may be aligned or not depending on
- // the segment properties (this matches MM player behaviour)
- //
- // This function - in contrast to buildPaths() - also checks noClose
- // flag and automatically closes polygons.
- //
- // TODO: Flash never aligns lines that are wider than 1 pixel on *screen*,
- // but we currently don't check the width.
- void buildPaths_rounded(AggPaths& dest,
- const GnashPaths& paths, const std::vector<LineStyle>& line_styles)
- {
-
- const float subpixel_offset = 0.5f;
-
- const size_t pcount = paths.size();
-
- dest.resize(pcount);
-
- for (size_t pno=0; pno<pcount; ++pno) {
-
- const Path& this_path = paths[pno];
- agg::path_storage& new_path = dest[pno];
-
- bool hinting=false, closed=false, hairline=false;
-
- if (this_path.m_line) {
- const LineStyle& lstyle = line_styles[this_path.m_line-1];
-
- hinting = lstyle.doPixelHinting();
- closed = this_path.isClosed() && !lstyle.noClose();
-
- // check if this line is a hairline ON SCREEN
- // TODO: we currently only check for hairlines per definiton, not
- // for thin lines that become hair lines due to scaling
- if (lstyle.getThickness()<=20)
- hairline = true;
- }
-
- float prev_ax = twipsToPixels(this_path.ap.x);
- float prev_ay = twipsToPixels(this_path.ap.y);
- bool prev_align_x = true;
- bool prev_align_y = true;
-
- size_t ecount = this_path.m_edges.size();
-
- // avoid extra edge when doing implicit close later
- if (closed && ecount &&
- this_path.m_edges.back().straight()) --ecount;
-
- for (size_t eno=0; eno<ecount; ++eno) {
-
- const Edge& this_edge = this_path.m_edges[eno];
-
- float this_ax = twipsToPixels(this_edge.ap.x);
- float this_ay = twipsToPixels(this_edge.ap.y);
-
- if (hinting || this_edge.straight()) {
-
- // candidate for alignment?
- bool align_x = hinting || (hairline && (prev_ax == this_ax));
- bool align_y = hinting || (hairline && (prev_ay == this_ay));
-
- if (align_x)
- this_ax = round(this_ax);
-
- if (align_y)
- this_ay = round(this_ay);
-
- // first line?
- if (eno==0) {
-
- if (align_x)
- prev_ax = round(prev_ax);
-
- if (align_y)
- prev_ay = round(prev_ay);
-
- new_path.move_to(prev_ax + subpixel_offset,
- prev_ay + subpixel_offset);
-
- } else {
-
- // not the first line, but the previous anchor point
- // might belong to a curve and thus may not be aligned.
- // We need to have both anchors of this new line to be
- // aligned, so it may be neccesary to add a line
- if ((align_x && !prev_align_x) || (align_y && !prev_align_y)) {
-
- if (align_x)
- prev_ax = round(prev_ax);
-
- if (align_y)
- prev_ay = round(prev_ay);
-
- new_path.line_to(prev_ax + subpixel_offset,
- prev_ay + subpixel_offset);
-
- }
-
- // TODO: (minor flaw) Flash player never aligns anchor points
- // of curves, even if they are attached to straight vertical
- // or horizontal lines. It can be seen easily with rounded
- // rectangles, where the curves are never aligned and all
- // straight lines are. AGG backend will align the curve anchor
- // point that follows the straight line. It's not a big problem
- // but it's not exact...
-
- }
-
- new_path.line_to(this_ax + subpixel_offset,
- this_ay + subpixel_offset);
-
- prev_align_x = align_x;
- prev_align_y = align_y;
-
-
- } else {
-
- // first line?
- if (eno==0)
- new_path.move_to(prev_ax, prev_ay);
-
- // never align curves!
- new_path.curve3(
- twipsToPixels(this_edge.cp.x) + subpixel_offset,
- twipsToPixels(this_edge.cp.y) + subpixel_offset,
- this_ax + subpixel_offset,
- this_ay + subpixel_offset);
-
- prev_align_x = false;
- prev_align_y = false;
-
- }
-
- prev_ax = this_ax;
- prev_ay = this_ay;
-
- } //for
-
- if (closed)
- new_path.close_polygon();
+ // Version of buildPaths that uses rounded coordinates (pixel hinting)
+ // for line styles that want it.
+ // This is used for outlines which are aligned to the pixel grid to avoid
+ // anti-aliasing problems (a perfect horizontal line being drawn over two
+ // lines and looking blurry). The proprietary player does this too.
+ //
+ // Not all points are aligned, only those lines that:
+ // - are straight
+ // - are pure horizontal or vertical
+ // Also, single segments of a path may be aligned or not depending on
+ // the segment properties (this matches MM player behaviour)
+ //
+ // This function - in contrast to buildPaths() - also checks noClose
+ // flag and automatically closes polygons.
+ //
+ // TODO: Flash never aligns lines that are wider than 1 pixel on *screen*,
+ // but we currently don't check the width.
+ void buildPaths_rounded(AggPaths& dest,
+ const GnashPaths& paths, const
std::vector<LineStyle>& line_styles)
+ {
+
+ const float subpixel_offset = 0.5f;
+
+ const size_t pcount = paths.size();
+
+ dest.resize(pcount);
+
+ for (size_t pno=0; pno<pcount; ++pno) {
+
+ const Path& this_path = paths[pno];
+ agg::path_storage& new_path = dest[pno];
+
+ bool hinting=false, closed=false, hairline=false;
+
+ if (this_path.m_line) {
+ const LineStyle& lstyle = line_styles[this_path.m_line-1];
+
+ hinting = lstyle.doPixelHinting();
+ closed = this_path.isClosed() && !lstyle.noClose();
+
+ // check if this line is a hairline ON SCREEN
+ // TODO: we currently only check for hairlines per
definiton, not
+ // for thin lines that become hair lines due to scaling
+ if (lstyle.getThickness()<=20)
+ hairline = true;
+ }
+
+ float prev_ax = twipsToPixels(this_path.ap.x);
+ float prev_ay = twipsToPixels(this_path.ap.y);
+ bool prev_align_x = true;
+ bool prev_align_y = true;
+
+ size_t ecount = this_path.m_edges.size();
+
+ // avoid extra edge when doing implicit close later
+ if (closed && ecount &&
+ this_path.m_edges.back().straight()) --ecount;
+
+ for (size_t eno=0; eno<ecount; ++eno) {
+
+ const Edge& this_edge = this_path.m_edges[eno];
+
+ float this_ax = twipsToPixels(this_edge.ap.x);
+ float this_ay = twipsToPixels(this_edge.ap.y);
+
+ if (hinting || this_edge.straight()) {
+
+ // candidate for alignment?
+ bool align_x = hinting || (hairline && (prev_ax ==
this_ax));
+ bool align_y = hinting || (hairline && (prev_ay ==
this_ay));
+
+ if (align_x) {
+ this_ax = round(this_ax);
+ }
+ if (align_y) {
+ this_ay = round(this_ay);
+ }
+
+ // first line?
+ if (eno==0) {
+ if (align_x) {
+ prev_ax = round(prev_ax);
+ }
+ if (align_y) {
+ prev_ay = round(prev_ay);
+ }
+ new_path.move_to(prev_ax + subpixel_offset,
+ prev_ay + subpixel_offset);
+ } else {
+
+ // not the first line, but the previous anchor point
+ // might belong to a curve and thus may not be
aligned.
+ // We need to have both anchors of this new line to
be
+ // aligned, so it may be neccesary to add a line
+ if ((align_x && !prev_align_x) || (align_y &&
!prev_align_y)) {
+
+ if (align_x)
+ prev_ax = round(prev_ax);
+
+ if (align_y)
+ prev_ay = round(prev_ay);
+
+ new_path.line_to(prev_ax + subpixel_offset,
+ prev_ay + subpixel_offset);
+
+ }
+
+ // TODO: (minor flaw) Flash player never aligns
anchor points
+ // of curves, even if they are attached to straight
vertical
+ // or horizontal lines. It can be seen easily with
rounded
+ // rectangles, where the curves are never aligned
and all
+ // straight lines are. AGG backend will align the
curve anchor
+ // point that follows the straight line. It's not a
big problem
+ // but it's not exact...
+
+ }
+
+ new_path.line_to(this_ax + subpixel_offset,
+ this_ay + subpixel_offset);
+
+ prev_align_x = align_x;
+ prev_align_y = align_y;
+
+
+ } else {
+
+ // first line?
+ if (eno==0)
+ new_path.move_to(prev_ax, prev_ay);
+
+ // never align curves!
+ new_path.curve3(
+ twipsToPixels(this_edge.cp.x) + subpixel_offset,
+ twipsToPixels(this_edge.cp.y) + subpixel_offset,
+ this_ax + subpixel_offset,
+ this_ay + subpixel_offset);
+
+ prev_align_x = false;
+ prev_align_y = false;
+
+ }
+
+ prev_ax = this_ax;
+ prev_ay = this_ay;
+
+ } //for
+
+ if (closed)
+ new_path.close_polygon();
+
+ }
+ } //buildPaths_rounded
- }
- } //buildPaths_rounded
-
// Initializes the internal styles class for AGG renderer
void build_agg_styles(StyleHandler& sh,
- const std::vector<FillStyle>& FillStyles,
- const SWFMatrix& fillstyle_matrix, const SWFCxForm& cx) {
-
+ const std::vector<FillStyle>& FillStyles,
+ const SWFMatrix& fillstyle_matrix, const SWFCxForm&
cx) {
+
SWFMatrix inv_stage_matrix = stage_matrix;
inv_stage_matrix.invert();
-
+
const size_t fcount = FillStyles.size();
-
+
for (size_t fno = 0; fno < fcount; ++fno) {
const AddStyles st(stage_matrix, fillstyle_matrix, cx, sh,
- _quality);
+ _quality);
boost::apply_visitor(st, FillStyles[fno].fill);
}
}
-
-
- /// Draws the given path using the given fill style and color transform.
- //
- /// Normally, Flash shapes are drawn using even-odd filling rule. However,
- /// for glyphs non-zero filling rule should be used (even_odd=0).
- /// Note the paths have already been transformed by the SWFMatrix and
- /// 'subshape_id' defines which sub-shape should be drawn (-1 means all
- /// subshapes).
- ///
- /// Note the *coordinates* in "paths" are not used because they are
- /// already prepared in agg_paths. The (nearly ambiguous) "path" parameter
- /// is used to access other properties like fill styles and subshapes.
- ///
- /// @param subshape_id
- /// Defines which subshape to draw. -1 means all subshapes.
- ///
- void draw_shape(int subshape_id, const GnashPaths &paths,
- const AggPaths& agg_paths,
- StyleHandler& sh, bool even_odd) {
-
- if (_alphaMasks.empty()) {
-
- // No mask active, use normal scanline renderer
-
- typedef agg::scanline_u8 scanline_type;
-
- scanline_type sl;
-
- draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
- sh, even_odd, sl);
-
- } else {
- // Mask is active, use alpha mask scanline renderer
-
- typedef agg::scanline_u8_am<agg::alpha_mask_gray8> scanline_type;
-
- scanline_type sl(_alphaMasks.back()->getMask());
-
- draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
- sh, even_odd, sl);
-
- }
- }
-
- /// Template for draw_shape(). Two different scanline types are suppored,
- /// one with and one without an alpha mask. This makes drawing without masks
- /// much faster.
- template <class scanline_type>
- void draw_shape_impl(int subshape_id, const GnashPaths &paths,
- const AggPaths& agg_paths,
- StyleHandler& sh, bool even_odd, scanline_type& sl) {
- /*
- Fortunately, AGG provides a rasterizer that fits perfectly to the flash
- data model. So we just have to feed AGG with all data and we're done. :-)
- This is also far better than recomposing the polygons as the rasterizer
- can do everything in one pass and it is also better for adjacent edges
- (anti aliasing).
- Thank to Maxim Shemanarev for providing us such a great tool with AGG...
- */
+ /// Draws the given path using the given fill style and color transform.
+ //
+ /// Normally, Flash shapes are drawn using even-odd filling rule. However,
+ /// for glyphs non-zero filling rule should be used (even_odd=0).
+ /// Note the paths have already been transformed by the SWFMatrix and
+ /// 'subshape_id' defines which sub-shape should be drawn (-1 means all
+ /// subshapes).
+ ///
+ /// Note the *coordinates* in "paths" are not used because they are
+ /// already prepared in agg_paths. The (nearly ambiguous) "path" parameter
+ /// is used to access other properties like fill styles and subshapes.
+ ///
+ /// @param subshape_id
+ /// Defines which subshape to draw. -1 means all subshapes.
+ ///
+ void draw_shape(int subshape_id, const GnashPaths &paths,
+ const AggPaths& agg_paths,
+ StyleHandler& sh, bool even_odd) {
+
+ if (_alphaMasks.empty()) {
+
+ // No mask active, use normal scanline renderer
+
+ typedef agg::scanline_u8 scanline_type;
+
+ scanline_type sl;
+
+ draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
+ sh, even_odd, sl);
+
+ } else {
+
+ // Mask is active, use alpha mask scanline renderer
+
+ typedef agg::scanline_u8_am<agg::alpha_mask_gray8> scanline_type;
+
+ scanline_type sl(_alphaMasks.back()->getMask());
+
+ draw_shape_impl<scanline_type> (subshape_id, paths, agg_paths,
+ sh, even_odd, sl);
+
+ }
+
+ }
- assert(m_pixf.get());
+ /// Template for draw_shape(). Two different scanline types are suppored,
+ /// one with and one without an alpha mask. This makes drawing without
masks
+ /// much faster.
+ template <class scanline_type>
+ void draw_shape_impl(int subshape_id, const GnashPaths &paths,
+ const AggPaths& agg_paths,
+ StyleHandler& sh, bool even_odd, scanline_type& sl) {
+ /*
+ Fortunately, AGG provides a rasterizer that fits perfectly to the
flash
+ data model. So we just have to feed AGG with all data and we're done.
:-)
+ This is also far better than recomposing the polygons as the
rasterizer
+ can do everything in one pass and it is also better for adjacent edges
+ (anti aliasing).
+ Thank to Maxim Shemanarev for providing us such a great tool with
AGG...
+ */
+
+ assert(m_pixf.get());
- assert(!m_drawing_mask);
+ assert(!m_drawing_mask);
- if ( _clipbounds.empty() ) return;
+ if ( _clipbounds.empty() ) return;
- // Target renderer
- renderer_base& rbase = *m_rbase;
+ // Target renderer
+ renderer_base& rbase = *m_rbase;
- typedef agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_int> ras_type;
- ras_type rasc; // flash-like renderer
+ typedef agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_int>
ras_type;
+ ras_type rasc; // flash-like renderer
- agg::renderer_scanline_aa_solid<
- agg::renderer_base<PixelFormat> > ren_sl(rbase); // solid fills
- agg::span_allocator<agg::rgba8> alloc; // span allocator (?)
+ agg::renderer_scanline_aa_solid<
+ agg::renderer_base<PixelFormat> > ren_sl(rbase); // solid fills
+ agg::span_allocator<agg::rgba8> alloc; // span allocator (?)
- // activate even-odd filling rule
- if (even_odd)
- rasc.filling_rule(agg::fill_even_odd);
- else
- rasc.filling_rule(agg::fill_non_zero);
+ // activate even-odd filling rule
+ if (even_odd)
+ rasc.filling_rule(agg::fill_even_odd);
+ else
+ rasc.filling_rule(agg::fill_non_zero);
- for (unsigned int cno=0; cno<_clipbounds_selected.size(); ++cno) {
-
- const geometry::Range2d<int>* bounds = _clipbounds_selected[cno];
-
- applyClipBox<ras_type> (rasc, *bounds);
-
- int current_subshape=0;
-
- // push paths to AGG
- const size_t pcount = paths.size();
-
- for (size_t pno=0; pno<pcount; ++pno) {
-
- const Path &this_path_gnash = paths[pno];
- agg::path_storage &this_path_agg =
- const_cast<agg::path_storage&>(agg_paths[pno]);
-
- agg::conv_curve<agg::path_storage> curve(this_path_agg);
-
- if (this_path_gnash.m_new_shape) ++current_subshape;
-
- if ((subshape_id >= 0) && (current_subshape!=subshape_id)) {
- // Skip this path as it is not part of the requested sub-shape.
- continue;
- }
-
- if ((this_path_gnash.m_fill0==0) && (this_path_gnash.m_fill1==0)) {
- // Skip this path as it contains no fill style
- continue;
- }
+ for (unsigned int cno=0; cno<_clipbounds_selected.size(); ++cno) {
+
+ const geometry::Range2d<int>* bounds = _clipbounds_selected[cno];
+
+ applyClipBox<ras_type> (rasc, *bounds);
+
+ int current_subshape=0;
+
+ // push paths to AGG
+ const size_t pcount = paths.size();
+
+ for (size_t pno=0; pno<pcount; ++pno) {
+
+ const Path &this_path_gnash = paths[pno];
+ agg::path_storage &this_path_agg =
+ const_cast<agg::path_storage&>(agg_paths[pno]);
+
+ agg::conv_curve<agg::path_storage> curve(this_path_agg);
+
+ if (this_path_gnash.m_new_shape) ++current_subshape;
+
+ if ((subshape_id >= 0) && (current_subshape!=subshape_id)) {
+ // Skip this path as it is not part of the requested
sub-shape.
+ continue;
+ }
+
+ if ((this_path_gnash.m_fill0==0) &&
(this_path_gnash.m_fill1==0)) {
+ // Skip this path as it contains no fill style
+ continue;
+ }
-
- // Tell the rasterizer which styles the following path will use.
- // The good thing is, that it already supports two fill styles out of
- // the box.
- // Flash uses value "0" for "no fill", whereas AGG uses "-1" for that.
- rasc.styles(this_path_gnash.m_fill0-1, this_path_gnash.m_fill1-1);
+
+ // Tell the rasterizer which styles the following path will use.
+ // The good thing is, that it already supports two fill styles
out of
+ // the box.
+ // Flash uses value "0" for "no fill", whereas AGG uses "-1"
for that.
+ rasc.styles(this_path_gnash.m_fill0-1,
this_path_gnash.m_fill1-1);
- // add path to the compound rasterizer
- rasc.add_path(curve);
-
- }
-
- agg::render_scanlines_compound_layered(rasc, sl, rbase, alloc, sh);
- }
-
- } // draw_shape_impl
-
-
-
-
- // very similar to draw_shape but used for generating masks. There are no
- // fill styles nor subshapes and such. Just render plain solid shapes.
- void draw_mask_shape(const GnashPaths& paths, bool even_odd)
- {
-
- const AlphaMasks::size_type mask_count = _alphaMasks.size();
-
- if (mask_count < 2) {
-
- // This is the first level mask
-
- typedef agg::scanline_u8 scanline_type;
-
- scanline_type sl;
-
- draw_mask_shape_impl(paths, even_odd, sl);
-
- }
- else {
-
- // Woohoo! We're drawing a nested mask! Use the previous mask while
- // drawing the new one, the result will be the intersection.
-
- typedef agg::scanline_u8_am<agg::alpha_mask_gray8> scanline_type;
-
- scanline_type sl(_alphaMasks[mask_count-2]->getMask());
-
- draw_mask_shape_impl(paths, even_odd, sl);
-
- }
-
- }
-
-
- template <class scanline_type>
- void draw_mask_shape_impl(const GnashPaths& paths, bool even_odd,
- scanline_type& sl) {
-
- typedef agg::pixfmt_gray8 pixfmt;
- typedef agg::renderer_base<pixfmt> renderer_base;
-
- assert(!_alphaMasks.empty());
-
- // dummy style handler
- typedef agg_mask_style_handler sh_type;
- sh_type sh;
-
- // compound rasterizer used for flash shapes
- typedef agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_int> rasc_type;
- rasc_type rasc;
+ // add path to the compound rasterizer
+ rasc.add_path(curve);
+
+ }
+
+ agg::render_scanlines_compound_layered(rasc, sl, rbase, alloc, sh);
+ }
+
+ } // draw_shape_impl
+
+ // very similar to draw_shape but used for generating masks. There are no
+ // fill styles nor subshapes and such. Just render plain solid shapes.
+ void draw_mask_shape(const GnashPaths& paths, bool even_odd)
+ {
+ const AlphaMasks::size_type mask_count = _alphaMasks.size();
+ if (mask_count < 2) {
+
+ // This is the first level mask
+ typedef agg::scanline_u8 scanline_type;
+ scanline_type sl;
+ draw_mask_shape_impl(paths, even_odd, sl);
+ } else {
+ // Woohoo! We're drawing a nested mask! Use the previous mask
while
+ // drawing the new one, the result will be the intersection.
+ typedef agg::scanline_u8_am<agg::alpha_mask_gray8>
scanline_type;
+ scanline_type sl(_alphaMasks[mask_count-2]->getMask());
+ draw_mask_shape_impl(paths, even_odd, sl);
+ }
+ }
+ template <class scanline_type>
+ void draw_mask_shape_impl(const GnashPaths& paths, bool even_odd,
+ scanline_type& sl) {
+
+ typedef agg::pixfmt_gray8 pixfmt;
+ typedef agg::renderer_base<pixfmt> renderer_base;
+
+ assert(!_alphaMasks.empty());
+
+ // dummy style handler
+ typedef agg_mask_style_handler sh_type;
+ sh_type sh;
+
+ // compound rasterizer used for flash shapes
+ typedef agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_int>
rasc_type;
+ rasc_type rasc;
+
+
+ // activate even-odd filling rule
+ if (even_odd) rasc.filling_rule(agg::fill_even_odd);
+ else rasc.filling_rule(agg::fill_non_zero);
+
+ // push paths to AGG
+ agg::path_storage path;
+ agg::conv_curve<agg::path_storage> curve(path);
+
+ for (size_t pno=0, pcount=paths.size(); pno < pcount; ++pno) {
+
+ const Path& this_path = paths[pno];
- // activate even-odd filling rule
- if (even_odd) rasc.filling_rule(agg::fill_even_odd);
- else rasc.filling_rule(agg::fill_non_zero);
-
- // push paths to AGG
- agg::path_storage path;
- agg::conv_curve<agg::path_storage> curve(path);
-
- for (size_t pno=0, pcount=paths.size(); pno < pcount; ++pno) {
-
- const Path& this_path = paths[pno];
-
- path.remove_all();
+ path.remove_all();
- // reduce everything to just one fill style!
- rasc.styles(this_path.m_fill0==0 ? -1 : 0,
- this_path.m_fill1==0 ? -1 : 0);
+ // reduce everything to just one fill style!
+ rasc.styles(this_path.m_fill0==0 ? -1 : 0,
+ this_path.m_fill1==0 ? -1 : 0);
- // starting point of path
- path.move_to(twipsToPixels(this_path.ap.x),
- twipsToPixels(this_path.ap.y));
+ // starting point of path
+ path.move_to(twipsToPixels(this_path.ap.x),
+ twipsToPixels(this_path.ap.y));
- // Add all edges to the path.
- std::for_each(this_path.m_edges.begin(), this_path.m_edges.end(),
- EdgeToPath(path));
+ // Add all edges to the path.
+ std::for_each(this_path.m_edges.begin(), this_path.m_edges.end(),
+ EdgeToPath(path));
- // add to rasterizer
- rasc.add_path(curve);
+ // add to rasterizer
+ rasc.add_path(curve);
- } // for path
+ } // for path
- // renderer base
- renderer_base& rbase = _alphaMasks.back()->get_rbase();
+ // renderer base
+ renderer_base& rbase = _alphaMasks.back()->get_rbase();
- // span allocator
- typedef agg::span_allocator<agg::gray8> alloc_type;
- alloc_type alloc;
+ // span allocator
+ typedef agg::span_allocator<agg::gray8> alloc_type;
+ alloc_type alloc;
- // now render that thing!
- agg::render_scanlines_compound_layered (rasc, sl, rbase, alloc, sh);
+ // now render that thing!
+ agg::render_scanlines_compound_layered (rasc, sl, rbase, alloc, sh);
- } // draw_mask_shape
+ } // draw_mask_shape
- /// Just like draw_shapes() except that it draws an outline.
- void draw_outlines(int subshape_id, const GnashPaths &paths,
- const AggPaths& agg_paths,
- const std::vector<LineStyle> &line_styles, const SWFCxForm& cx,
- const SWFMatrix& linestyle_matrix) {
+ /// Just like draw_shapes() except that it draws an outline.
+ void draw_outlines(int subshape_id, const GnashPaths &paths,
+ const AggPaths& agg_paths,
+ const std::vector<LineStyle> &line_styles, const
SWFCxForm& cx,
+ const SWFMatrix& linestyle_matrix) {
- if (_alphaMasks.empty()) {
+ if (_alphaMasks.empty()) {
- // No mask active, use normal scanline renderer
+ // No mask active, use normal scanline renderer
- typedef agg::scanline_u8 scanline_type;
+ typedef agg::scanline_u8 scanline_type;
- scanline_type sl;
+ scanline_type sl;
- draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
- line_styles, cx, linestyle_matrix, sl);
+ draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
+ line_styles, cx,
linestyle_matrix, sl);
- } else {
+ } else {
- // Mask is active, use alpha mask scanline renderer
+ // Mask is active, use alpha mask scanline renderer
- typedef agg::scanline_u8_am<agg::alpha_mask_gray8> scanline_type;
+ typedef agg::scanline_u8_am<agg::alpha_mask_gray8> scanline_type;
- scanline_type sl(_alphaMasks.back()->getMask());
+ scanline_type sl(_alphaMasks.back()->getMask());
- draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
- line_styles, cx, linestyle_matrix, sl);
+ draw_outlines_impl<scanline_type> (subshape_id, paths, agg_paths,
+ line_styles, cx,
linestyle_matrix, sl);
- }
+ }
- } //draw_outlines
+ } //draw_outlines
- /// Template for draw_outlines(), see draw_shapes_impl().
- template <class scanline_type>
- void draw_outlines_impl(int subshape_id, const GnashPaths &paths,
- const AggPaths& agg_paths,
- const std::vector<LineStyle> &line_styles, const SWFCxForm& cx,
- const SWFMatrix& linestyle_matrix, scanline_type& sl) {
+ /// Template for draw_outlines(), see draw_shapes_impl().
+ template <class scanline_type>
+ void draw_outlines_impl(int subshape_id, const GnashPaths &paths,
+ const AggPaths& agg_paths,
+ const std::vector<LineStyle> &line_styles, const
SWFCxForm& cx,
+ const SWFMatrix& linestyle_matrix, scanline_type&
sl) {
- assert(m_pixf.get());
+ assert(m_pixf.get());
- // Flash ignores lines in mask /definitions/
- if (m_drawing_mask) return;
+ // Flash ignores lines in mask /definitions/
+ if (m_drawing_mask) return;
- if ( _clipbounds.empty() ) return;
+ if ( _clipbounds.empty() ) return;
- // TODO: While walking the paths for filling them, remember when a path
- // has a line style associated, so that we avoid walking the paths again
- // when there really are no outlines to draw...
+ // TODO: While walking the paths for filling them, remember when a path
+ // has a line style associated, so that we avoid walking the paths again
+ // when there really are no outlines to draw...
- // use avg between x and y scale
- const float stroke_scale = (std::abs(linestyle_matrix.get_x_scale()) +
- std::abs(linestyle_matrix.get_y_scale())) / 2.0f * get_stroke_scale();
+ // use avg between x and y scale
+ const float stroke_scale = (std::abs(linestyle_matrix.get_x_scale()) +
+ std::abs(linestyle_matrix.get_y_scale())) /
2.0f * get_stroke_scale();
- // AGG stuff
- typedef agg::rasterizer_scanline_aa<> ras_type;
- ras_type ras; // anti alias
+ // AGG stuff
+ typedef agg::rasterizer_scanline_aa<> ras_type;
+ ras_type ras; // anti alias
- renderer_base& rbase = *m_rbase;
+ renderer_base& rbase = *m_rbase;
- agg::renderer_scanline_aa_solid<
- agg::renderer_base<PixelFormat> > ren_sl(rbase); // solid fills
+ agg::renderer_scanline_aa_solid<
+ agg::renderer_base<PixelFormat> > ren_sl(rbase); // solid fills
- for (unsigned int cno=0; cno<_clipbounds_selected.size(); ++cno) {
+ for (unsigned int cno=0; cno<_clipbounds_selected.size(); ++cno) {
- const geometry::Range2d<int>* bounds = _clipbounds_selected[cno];
+ const geometry::Range2d<int>* bounds = _clipbounds_selected[cno];
- applyClipBox<ras_type> (ras, *bounds);
+ applyClipBox<ras_type> (ras, *bounds);
- int current_subshape=0;
+ int current_subshape=0;
- for (size_t pno=0, pcount=paths.size(); pno<pcount; ++pno) {
+ for (size_t pno=0, pcount=paths.size(); pno<pcount; ++pno) {
- const Path& this_path_gnash = paths[pno];
+ const Path& this_path_gnash = paths[pno];
- agg::path_storage &this_path_agg =
- const_cast<agg::path_storage&>(agg_paths[pno]);
+ agg::path_storage &this_path_agg =
+ const_cast<agg::path_storage&>(agg_paths[pno]);
- if (this_path_gnash.m_new_shape)
- ++current_subshape;
+ if (this_path_gnash.m_new_shape)
+ ++current_subshape;
- if ((subshape_id>=0) && (current_subshape!=subshape_id)) {
- // Skip this path as it is not part of the requested sub-shape.
- continue;
- }
+ if ((subshape_id>=0) && (current_subshape!=subshape_id)) {
+ // Skip this path as it is not part of the requested
sub-shape.
+ continue;
+ }
- if (this_path_gnash.m_line==0) {
- // Skip this path as it contains no line style
- continue;
- }
+ if (this_path_gnash.m_line==0) {
+ // Skip this path as it contains no line style
+ continue;
+ }
- agg::conv_curve< agg::path_storage > curve(this_path_agg); // to
render curves
- agg::conv_stroke< agg::conv_curve < agg::path_storage > >
- stroke(curve); // to get an outline
+ agg::conv_curve< agg::path_storage > curve(this_path_agg); //
to render curves
+ agg::conv_stroke< agg::conv_curve < agg::path_storage > >
+ stroke(curve); // to get an outline
- const LineStyle& lstyle = line_styles[this_path_gnash.m_line-1];
+ const LineStyle& lstyle = line_styles[this_path_gnash.m_line-1];
- int thickness = lstyle.getThickness();
- if (!thickness) stroke.width(1); // hairline
- else if ( (!lstyle.scaleThicknessVertically()) &&
(!lstyle.scaleThicknessHorizontally()) )
- {
- stroke.width(twipsToPixels(thickness));
- }
- else
- {
- if ((!lstyle.scaleThicknessVertically()) ||
- (!lstyle.scaleThicknessHorizontally()))
- {
- LOG_ONCE( log_unimpl(_("Unidirectionally scaled strokes in "
- "AGG renderer (we'll scale by the "
- "scalable one)")) );
- }
- stroke.width(std::max(1.0f, thickness*stroke_scale));
- }
-
- // TODO: support endCapStyle
-
- // TODO: When lstyle.noClose==0 and the start and end point matches,
- // then render a real join instead of the caps.
-
- switch (lstyle.startCapStyle()) {
- case CAP_NONE : stroke.line_cap(agg::butt_cap); break;
- case CAP_SQUARE : stroke.line_cap(agg::square_cap); break;
- default : case CAP_ROUND : stroke.line_cap(agg::round_cap);
- }
-
- switch (lstyle.joinStyle()) {
- case JOIN_BEVEL : stroke.line_join(agg::bevel_join); break;
- case JOIN_MITER : stroke.line_join(agg::miter_join); break;
- default : case JOIN_ROUND : stroke.line_join(agg::round_join);
- }
-
- stroke.miter_limit(lstyle.miterLimitFactor());
+ int thickness = lstyle.getThickness();
+ if (!thickness) stroke.width(1); // hairline
+ else if ( (!lstyle.scaleThicknessVertically()) &&
(!lstyle.scaleThicknessHorizontally()) )
+ {
+ stroke.width(twipsToPixels(thickness));
+ } else {
+ if ((!lstyle.scaleThicknessVertically()) ||
+ (!lstyle.scaleThicknessHorizontally())) {
+ LOG_ONCE( log_unimpl(_("Unidirectionally scaled strokes
in "
+ "AGG renderer (we'll scale by
the "
+ "scalable one)")) );
+ }
+ stroke.width(std::max(1.0f, thickness*stroke_scale));
+ }
+
+ // TODO: support endCapStyle
+
+ // TODO: When lstyle.noClose==0 and the start and end point
matches,
+ // then render a real join instead of the caps.
+
+ switch (lstyle.startCapStyle()) {
+ case CAP_NONE : stroke.line_cap(agg::butt_cap); break;
+ case CAP_SQUARE : stroke.line_cap(agg::square_cap); break;
+ default : case CAP_ROUND : stroke.line_cap(agg::round_cap);
+ }
+
+ switch (lstyle.joinStyle()) {
+ case JOIN_BEVEL : stroke.line_join(agg::bevel_join); break;
+ case JOIN_MITER : stroke.line_join(agg::miter_join); break;
+ default : case JOIN_ROUND : stroke.line_join(agg::round_join);
+ }
+
+ stroke.miter_limit(lstyle.miterLimitFactor());
- ras.reset();
- ras.add_path(stroke);
-
- rgba color = cx.transform(lstyle.get_color());
- ren_sl.color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
color.m_a));
-
- agg::render_scanlines(ras, sl, ren_sl);
-
- }
-
-
- }
-
- } // draw_outlines_impl
-
-
-
- /// Draws the given polygon.
- template <class scanline_type>
- void draw_poly_impl(const point* corners, size_t corner_count, const rgba&
fill,
- const rgba& outline, scanline_type& sl, const SWFMatrix& poly_mat) {
-
- assert(m_pixf.get());
-
- if (corner_count<1) return;
-
- if ( _clipbounds.empty() ) return;
-
- SWFMatrix mat = stage_matrix;
- mat.concatenate(poly_mat);
+ ras.reset();
+ ras.add_path(stroke);
+
+ rgba color = cx.transform(lstyle.get_color());
+ ren_sl.color(agg::rgba8_pre(color.m_r, color.m_g, color.m_b,
color.m_a));
+ agg::render_scanlines(ras, sl, ren_sl);
+
+ }
+ }
+
+ } // draw_outlines_impl
- typedef agg::rasterizer_scanline_aa<> ras_type;
- renderer_base& rbase = *m_rbase;
+ /// Draws the given polygon.
+ template <class scanline_type>
+ void draw_poly_impl(const point* corners, size_t corner_count, const rgba&
fill,
+ const rgba& outline, scanline_type& sl, const
SWFMatrix& poly_mat) {
+
+ assert(m_pixf.get());
+
+ if (corner_count<1) return;
+
+ if ( _clipbounds.empty() ) return;
+
+ SWFMatrix mat = stage_matrix;
+ mat.concatenate(poly_mat);
+
+ typedef agg::rasterizer_scanline_aa<> ras_type;
+ renderer_base& rbase = *m_rbase;
- ras_type ras;
- agg::renderer_scanline_aa_solid<
- agg::renderer_base<PixelFormat> > ren_sl(rbase);
+ ras_type ras;
+ agg::renderer_scanline_aa_solid<
+ agg::renderer_base<PixelFormat> > ren_sl(rbase);
- // -- create path --
- agg::path_storage path;
- point pnt, origin;
+ // -- create path --
+ agg::path_storage path;
+ point pnt, origin;
- // Note: The coordinates are rounded and 0.5 is added to snap them to the
- // center of the pixel. This avoids blurring caused by anti-aliasing.
+ // Note: The coordinates are rounded and 0.5 is added to snap them to
the
+ // center of the pixel. This avoids blurring caused by anti-aliasing.
- // The default conversion of the boost converter is truncation.
- boost::numeric::converter<int,float> truncator;
+ // The default conversion of the boost converter is truncation.
+ boost::numeric::converter<int,float> truncator;
- mat.transform(&origin,
- point(truncator(corners[0].x), truncator(corners[0].y)));
- path.move_to(truncator(origin.x)+0.5, truncator(origin.y)+0.5);
+ mat.transform(&origin,
+ point(truncator(corners[0].x), truncator(corners[0].y)));
+ path.move_to(truncator(origin.x)+0.5, truncator(origin.y)+0.5);
- for (unsigned int i=1; i<corner_count; ++i) {
-
- mat.transform(&pnt, point(corners[i].x, corners[i].y));
-
- path.line_to(truncator(pnt.x)+0.5, truncator(pnt.y)+0.5);
- }
+ for (unsigned int i=1; i<corner_count; ++i) {
+ mat.transform(&pnt, point(corners[i].x, corners[i].y));
+ path.line_to(truncator(pnt.x)+0.5, truncator(pnt.y)+0.5);
+ }
- // close polygon
- path.line_to(truncator(origin.x)+0.5, truncator(origin.y)+0.5);
+ // close polygon
+ path.line_to(truncator(origin.x)+0.5, truncator(origin.y)+0.5);
- // -- render --
+ // -- render --
- // iterate through clipping bounds
- for (unsigned int cno=0; cno<_clipbounds.size(); ++cno) {
+ // iterate through clipping bounds
+ for (unsigned int cno=0; cno<_clipbounds.size(); ++cno) {
- const ClipBounds::value_type& bounds = _clipbounds[cno];
- applyClipBox<ras_type> (ras, bounds);
+ const ClipBounds::value_type& bounds = _clipbounds[cno];
+ applyClipBox<ras_type> (ras, bounds);
- // fill polygon
- if (fill.m_a>0) {
- ras.add_path(path);
- ren_sl.color(agg::rgba8_pre(fill.m_r, fill.m_g, fill.m_b, fill.m_a));
+ // fill polygon
+ if (fill.m_a>0) {
+ ras.add_path(path);
+ ren_sl.color(agg::rgba8_pre(fill.m_r, fill.m_g, fill.m_b,
fill.m_a));
- agg::render_scanlines(ras, sl, ren_sl);
- }
+ agg::render_scanlines(ras, sl, ren_sl);
+ }
- // draw outline
- if (outline.m_a>0) {
- agg::conv_stroke<agg::path_storage> stroke(path);
+ // draw outline
+ if (outline.m_a>0) {
+ agg::conv_stroke<agg::path_storage> stroke(path);
- stroke.width(1);
+ stroke.width(1);
- ren_sl.color(agg::rgba8_pre(outline.m_r, outline.m_g, outline.m_b,
outline.m_a));
+ ren_sl.color(agg::rgba8_pre(outline.m_r, outline.m_g,
outline.m_b, outline.m_a));
- ras.add_path(stroke);
+ ras.add_path(stroke);
- agg::render_scanlines(ras, sl, ren_sl);
- }
- }
+ agg::render_scanlines(ras, sl, ren_sl);
+ }
+ }
- } //draw_poly_impl
+ } //draw_poly_impl
- void drawPoly(const point* corners, size_t corner_count, const rgba& fill,
- const rgba& outline, const SWFMatrix& mat, bool masked) {
+ void drawPoly(const point* corners, size_t corner_count, const rgba& fill,
+ const rgba& outline, const SWFMatrix& mat, bool masked) {
- GNASH_REPORT_FUNCTION;
- if (masked && !_alphaMasks.empty()) {
+ if (masked && !_alphaMasks.empty()) {
- // apply mask
+ // apply mask
- typedef agg::scanline_u8_am<agg::alpha_mask_gray8> sl_type;
+ typedef agg::scanline_u8_am<agg::alpha_mask_gray8> sl_type;
- sl_type sl(_alphaMasks.back()->getMask());
+ sl_type sl(_alphaMasks.back()->getMask());
- draw_poly_impl<sl_type> (corners, corner_count, fill, outline, sl, mat);
+ draw_poly_impl<sl_type> (corners, corner_count, fill, outline, sl,
mat);
- } else {
+ } else {
- // no mask
+ // no mask
- typedef agg::scanline_p8 sl_type; // packed scanline (faster for solid
fills)
+ typedef agg::scanline_p8 sl_type; // packed scanline (faster for
solid fills)
- sl_type sl;
+ sl_type sl;
- draw_poly_impl<sl_type> (corners, corner_count, fill, outline, sl, mat);
+ draw_poly_impl<sl_type> (corners, corner_count, fill, outline, sl,
mat);
- }
+ }
- }
+ }
- inline float get_stroke_scale() {
- return (stage_matrix.get_x_scale() + stage_matrix.get_y_scale()) / 2.0f;
- }
+ inline float get_stroke_scale() {
+ return (stage_matrix.get_x_scale() + stage_matrix.get_y_scale()) / 2.0f;
+ }
- inline void world_to_pixel(int& x, int& y,
- float world_x, float world_y)
- {
- // negative pixels seems ok here... we don't
- // clip to valid range, use world_to_pixel(SWFRect&)
- // and Intersect() against valid range instead.
- point p(world_x, world_y);
- stage_matrix.transform(p);
- x = (int)p.x;
- y = (int)p.y;
- }
-
- geometry::Range2d<int> world_to_pixel(const SWFRect& wb)
- {
- using namespace gnash::geometry;
-
- if ( wb.is_null() ) return Range2d<int>(nullRange);
- if ( wb.is_world() ) return Range2d<int>(worldRange);
-
- int xmin, ymin, xmax, ymax;
-
- world_to_pixel(xmin, ymin, wb.get_x_min(), wb.get_y_min());
- world_to_pixel(xmax, ymax, wb.get_x_max(), wb.get_y_max());
-
- return Range2d<int>(xmin, ymin, xmax, ymax);
- }
+ inline void world_to_pixel(int& x, int& y,
+ float world_x, float world_y)
+ {
+ // negative pixels seems ok here... we don't
+ // clip to valid range, use world_to_pixel(SWFRect&)
+ // and Intersect() against valid range instead.
+ point p(world_x, world_y);
+ stage_matrix.transform(p);
+ x = (int)p.x;
+ y = (int)p.y;
+ }
+
+ geometry::Range2d<int> world_to_pixel(const SWFRect& wb)
+ {
+ using namespace gnash::geometry;
+
+ if ( wb.is_null() ) return Range2d<int>(nullRange);
+ if ( wb.is_world() ) return Range2d<int>(worldRange);
+
+ int xmin, ymin, xmax, ymax;
+
+ world_to_pixel(xmin, ymin, wb.get_x_min(), wb.get_y_min());
+ world_to_pixel(xmax, ymax, wb.get_x_max(), wb.get_y_max());
+
+ return Range2d<int>(xmin, ymin, xmax, ymax);
+ }
- geometry::Range2d<int> world_to_pixel(const geometry::Range2d<int>& wb)
- {
- if (wb.isNull() || wb.isWorld()) return wb;
+ geometry::Range2d<int> world_to_pixel(const geometry::Range2d<int>& wb)
+ {
+ if (wb.isNull() || wb.isWorld()) return wb;
- int xmin, ymin, xmax, ymax;
+ int xmin, ymin, xmax, ymax;
- world_to_pixel(xmin, ymin, wb.getMinX(), wb.getMinY());
- world_to_pixel(xmax, ymax, wb.getMaxX(), wb.getMaxY());
+ world_to_pixel(xmin, ymin, wb.getMinX(), wb.getMinY());
+ world_to_pixel(xmax, ymax, wb.getMaxX(), wb.getMaxY());
- return geometry::Range2d<int>(xmin, ymin, xmax, ymax);
- }
+ return geometry::Range2d<int>(xmin, ymin, xmax, ymax);
+ }
- point
- pixel_to_world(int x, int y)
- {
- point p(x, y);
- SWFMatrix mat = stage_matrix;
- mat.invert().transform(p);
- return p;
- };
+ point
+ pixel_to_world(int x, int y)
+ {
+ point p(x, y);
+ SWFMatrix mat = stage_matrix;
+ mat.invert().transform(p);
+ return p;
+ };
- void set_invalidated_region_world() {
- InvalidatedRanges ranges;
- ranges.setWorld();
- set_invalidated_regions(ranges);
- }
+ void set_invalidated_region_world() {
+ InvalidatedRanges ranges;
+ ranges.setWorld();
+ set_invalidated_regions(ranges);
+ }
- virtual void set_invalidated_regions(const InvalidatedRanges& ranges) {
- using gnash::geometry::Range2d;
+ virtual void set_invalidated_regions(const InvalidatedRanges& ranges) {
+ using gnash::geometry::Range2d;
- int count=0;
+ int count=0;
- _clipbounds_selected.clear();
- _clipbounds.clear();
+ _clipbounds_selected.clear();
+ _clipbounds.clear();
- // TODO: cache 'visiblerect' and maintain in sync with
- // xres/yres.
- Range2d<int> visiblerect;
- if ( xres && yres ) visiblerect = Range2d<int>(0, 0, xres-1, yres-1);
+ // TODO: cache 'visiblerect' and maintain in sync with
+ // xres/yres.
+ Range2d<int> visiblerect;
+ if ( xres && yres ) visiblerect = Range2d<int>(0, 0, xres-1, yres-1);
- for (size_t rno=0; rno<ranges.size(); ++rno) {
+ for (size_t rno=0; rno<ranges.size(); ++rno) {
- const Range2d<int>& range = ranges.getRange(rno);
+ const Range2d<int>& range = ranges.getRange(rno);
- Range2d<int> pixbounds = world_to_pixel(range);
+ Range2d<int> pixbounds = world_to_pixel(range);
- geometry::Range2d<int> bounds = Intersection(pixbounds, visiblerect);
+ geometry::Range2d<int> bounds = Intersection(pixbounds,
visiblerect);
- if (bounds.isNull()) continue; // out of screen
+ if (bounds.isNull()) continue; // out of screen
- assert(bounds.isFinite());
+ assert(bounds.isFinite());
- _clipbounds.push_back(bounds);
+ _clipbounds.push_back(bounds);
- ++count;
- }
- //log_debug("%d inv. bounds in frame", count);
+ ++count;
+ }
+ //log_debug("%d inv. bounds in frame", count);
- }
+ }
- virtual bool bounds_in_clipping_area(const geometry::Range2d<int>& bounds) {
+ virtual bool bounds_in_clipping_area(const geometry::Range2d<int>& bounds)
{
- using gnash::geometry::Range2d;
+ using gnash::geometry::Range2d;
- Range2d<int> pixbounds = world_to_pixel(bounds);
+ Range2d<int> pixbounds = world_to_pixel(bounds);
- for (unsigned int cno=0; cno<_clipbounds.size(); ++cno) {
- if (Intersect(pixbounds, _clipbounds[cno]))
- return true;
+ for (unsigned int cno=0; cno<_clipbounds.size(); ++cno) {
+ if (Intersect(pixbounds, _clipbounds[cno]))
+ return true;
+ }
+ return false;
}
- return false;
- }
- bool getPixel(rgba& color_return, int x, int y) const {
+ bool getPixel(rgba& color_return, int x, int y) const {
- if ((x<0) || (y<0) || (x>=xres) || (y>=yres))
- return false;
+ if ((x<0) || (y<0) || (x>=xres) || (y>=yres))
+ return false;
- agg::rgba8 color = m_pixf->pixel(x, y);
+ agg::rgba8 color = m_pixf->pixel(x, y);
- color_return.m_r = color.r;
- color_return.m_g = color.g;
- color_return.m_b = color.b;
- color_return.m_a = color.a;
+ color_return.m_r = color.r;
+ color_return.m_g = color.g;
+ color_return.m_b = color.b;
+ color_return.m_a = color.a;
- return true;
- }
+ return true;
+ }
- void set_scale(float new_xscale, float new_yscale) {
+ void set_scale(float new_xscale, float new_yscale) {
- scale_set=true;
- stage_matrix.set_identity();
- stage_matrix.set_scale(new_xscale/20.0f, new_yscale/20.0f);
- }
+ scale_set=true;
+ stage_matrix.set_identity();
+ stage_matrix.set_scale(new_xscale/20.0f, new_yscale/20.0f);
+ }
- void set_translation(float xoff, float yoff) {
- stage_matrix.set_translation(xoff, yoff);
- }
+ void set_translation(float xoff, float yoff) {
+ stage_matrix.set_translation(xoff, yoff);
+ }
- virtual unsigned int getBytesPerPixel() const {
- return bpp/8;
- }
+ virtual unsigned int getBytesPerPixel() const {
+ return bpp/8;
+ }
private: // private variables
@@ -2111,87 +2045,85 @@ private: // private variables
// here)
bool is_little_endian_host() {
- union {
- boost::uint16_t word;
- struct {
- boost::uint8_t b1;
- boost::uint8_t b2;
- } s;
- } u;
+ union {
+ boost::uint16_t word;
+ struct {
+ boost::uint8_t b1;
+ boost::uint8_t b2;
+ } s;
+ } u;
- u.s.b1 = 1;
- u.s.b2 = 2;
+ u.s.b1 = 1;
+ u.s.b2 = 2;
- return u.word == 0x0201;
+ return u.word == 0x0201;
}
DSOEXPORT Renderer_agg_base* create_Renderer_agg(const char *pixelformat)
{
- GNASH_REPORT_FUNCTION;
-
- if (!pixelformat) return NULL;
+ if (!pixelformat) return NULL;
- if (is_little_endian_host())
- log_debug(_("Framebuffer pixel format is %s (little-endian host)"),
pixelformat);
- else
- log_debug(_("Framebuffer pixel format is %s (big-endian host)"),
pixelformat);
+ if (is_little_endian_host())
+ log_debug(_("Framebuffer pixel format is %s (little-endian host)"),
pixelformat);
+ else
+ log_debug(_("Framebuffer pixel format is %s (big-endian host)"),
pixelformat);
#ifdef PIXELFORMAT_RGB555
- if (!strcmp(pixelformat, "RGB555"))
- return new Renderer_agg<agg::pixfmt_rgb555_pre> (16); // yep, 16!
+ if (!strcmp(pixelformat, "RGB555"))
+ return new Renderer_agg<agg::pixfmt_rgb555_pre> (16); // yep, 16!
- else
+ else
#endif
#ifdef PIXELFORMAT_RGB565
- if (!strcmp(pixelformat, "RGB565") || !strcmp(pixelformat, "RGBA16"))
- return new Renderer_agg<agg::pixfmt_rgb565_pre> (16);
- else
+ if (!strcmp(pixelformat, "RGB565") || !strcmp(pixelformat, "RGBA16"))
+ return new Renderer_agg<agg::pixfmt_rgb565_pre> (16);
+ else
#endif
#ifdef PIXELFORMAT_RGB24
- if (!strcmp(pixelformat, "RGB24"))
- return new Renderer_agg<agg::pixfmt_rgb24_pre> (24);
- else
+ if (!strcmp(pixelformat, "RGB24"))
+ return new Renderer_agg<agg::pixfmt_rgb24_pre> (24);
+ else
#endif
#ifdef PIXELFORMAT_BGR24
- if (!strcmp(pixelformat, "BGR24"))
- return new Renderer_agg<agg::pixfmt_bgr24_pre> (24);
- else
+ if (!strcmp(pixelformat, "BGR24"))
+ return new Renderer_agg<agg::pixfmt_bgr24_pre> (24);
+ else
#endif
#ifdef PIXELFORMAT_RGBA32
- if (!strcmp(pixelformat, "RGBA32"))
- return new Renderer_agg<agg::pixfmt_rgba32_pre> (32);
- else
+ if (!strcmp(pixelformat, "RGBA32"))
+ return new Renderer_agg<agg::pixfmt_rgba32_pre> (32);
+ else
#endif
#ifdef PIXELFORMAT_BGRA32
- if (!strcmp(pixelformat, "BGRA32"))
- return new Renderer_agg<agg::pixfmt_bgra32_pre> (32);
+ if (!strcmp(pixelformat, "BGRA32"))
+ return new Renderer_agg<agg::pixfmt_bgra32_pre>
(32);
#endif
#ifdef PIXELFORMAT_RGBA32
- if (!strcmp(pixelformat, "ARGB32"))
- return new Renderer_agg<agg::pixfmt_argb32_pre> (32);
- else
+ if (!strcmp(pixelformat, "ARGB32"))
+ return new Renderer_agg<agg::pixfmt_argb32_pre> (32);
+ else
#endif
#ifdef PIXELFORMAT_BGRA32
- if (!strcmp(pixelformat, "ABGR32"))
- return new Renderer_agg<agg::pixfmt_abgr32_pre> (32);
+ if (!strcmp(pixelformat, "ABGR32"))
+ return new Renderer_agg<agg::pixfmt_abgr32_pre> (32);
- else
+ else
#endif
- {
- log_error("Unknown pixelformat: %s\n", pixelformat);
- return NULL;
- //abort();
- }
+ {
+ log_error("Unknown pixelformat: %s\n", pixelformat);
+ return NULL;
+ //abort();
+ }
- return NULL; // avoid compiler warning
+ return NULL; // avoid compiler warning
}
DSOEXPORT const char *agg_detect_pixel_format(unsigned int rofs,
- unsigned int rsize, unsigned int gofs, unsigned int gsize,
- unsigned int bofs, unsigned int bsize, unsigned int bpp)
+ unsigned int rsize, unsigned int
gofs, unsigned int gsize,
+ unsigned int bofs, unsigned int
bsize, unsigned int bpp)
{
if (!is_little_endian_host() && (bpp>=24)) {
@@ -2248,6 +2180,6 @@ DSOEXPORT const char *agg_detect_pixel_format(unsigned
int rofs,
// Local Variables:
// mode: C++
-// indent-tabs-mode: t
+// indent-tabs-mode: NIL
// End:
/* vim: set cindent tabstop=8 softtabstop=4 shiftwidth=4: */
http://git.savannah.gnu.org/cgit//commit/?id=2b011a109017894358505d78711bff446b9e3fc3
commit 2b011a109017894358505d78711bff446b9e3fc3
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 17:43:51 2011 -0700
Select a subset of possible input devices, in our case, just the Babbage
touchscreen.
diff --git a/gui/fb/fb.cpp b/gui/fb/fb.cpp
index c7b5409..36a5e91 100644
--- a/gui/fb/fb.cpp
+++ b/gui/fb/fb.cpp
@@ -221,9 +221,38 @@ FBGui::init(int argc, char *** argv)
// Initialize all the input devices
// Look for Mice that use the PS/2 mouse protocol
- _inputs = InputDevice::scanForDevices();
- if (_inputs.empty()) {
+ std::vector<boost::shared_ptr<InputDevice> > possibles
+ = InputDevice::scanForDevices();
+ if (possibles.empty()) {
log_error("Found no accessible input event devices");
+ } else {
+ log_debug("Found %d input event devices.", possibles.size());
+ }
+
+ std::vector<boost::shared_ptr<InputDevice> >::iterator it;
+ for (it=possibles.begin(); it!=possibles.end(); ++it) {
+ (*it)->dump();
+ if ((*it)->getType() == InputDevice::MOUSE) {
+ log_debug("WARNING: Mouse support disabled as it conflicts with
the input event support.");
+ // For now we only want keyboards input events, as the mouse
+ // interface default of /dev/input/mice supports hotpluging
devices,
+ // unlike the regular events.
+ // _inputs.push_back(*it);
+ }
+ if ((*it)->getType() == InputDevice::KEYBOARD) {
+ _inputs.push_back(*it);
+ }
+ if ((*it)->getType() == InputDevice::TOUCHSCREEN) {
+ log_debug("WARNING: Touchscreen support disabled as it conflicts
with the input event support.");
+// _inputs.push_back(*it);
+ }
+ if ((*it)->getType() == InputDevice::TABLET) {
+ log_debug("Enabling Babbage Touchscreen support");
+ _inputs.push_back(*it);
+ }
+ if ((*it)->getType() == InputDevice::POWERBUTTON) {
+ _inputs.push_back(*it);
+ }
}
#if 0
@@ -259,7 +288,7 @@ FBGui::init(int argc, char *** argv)
log_debug("X:%d, Y:%d", _xpos, _ypos);
#endif
- _validbounds.setTo(0, 0, _width - 1, _height - 1);
+_validbounds.setTo(0, 0, _width - 1, _height - 1);
_renderer.reset(renderer::openvg::create_handler(0));
@@ -283,7 +312,7 @@ FBGui::run()
// let the GUI recompute the x/y scale factors to best fit the whole screen
resize_view(_validbounds.width(), _validbounds.height());
-
+
// This loops endlessly at the frame rate
while (!terminate_request) {
// wait the "heartbeat" inteval
@@ -672,26 +701,34 @@ FBGui::checkForData()
boost::shared_ptr<InputDevice::input_data_t> ie = (*it)->popData();
if (ie) {
#if 0
- std::cerr << "Got data: " << ie->pressed;
+ std::cerr << "Got data: " << ((ie->pressed) ? "true" : "false");
std::cerr << ", " << ie->key << ", " << ie->modifier;
std::cerr << ", " << ie->x << ", " << ie->y << std::endl;
// cerr << "X = " << coords[0] << endl;
// cerr << "Y = " << coords[1] << endl;
#endif
- // Range check and convert the position
+#if 0
+ // Range check and convert the position from relative to
+ // absolute
boost::shared_array<int> coords =
MouseDevice::convertCoordinates(ie->x, ie->y,
getStage()->getStageWidth(),
getStage()->getStageHeight());
- // See if a mouse button was clicked
- if (ie->pressed) {
- notifyMouseClick(true);
- }
-
// The mouse was moved
if (coords) {
notifyMouseMove(coords[0], coords[1]);
}
+#endif
+ // See if a mouse button was clicked
+ //if (ie->pressed) {
+ notifyMouseClick(true);
+ double x = 0.655 * ie->x;
+ double y = 0.46875 * ie->y;
+ log_debug("Mouse clicked at: %g:%g", x, y);
+ notifyMouseMove(ie->x, ie->y);
+// notifyMouseMove(int(x), int(y));
+// }
+
}
}
}
diff --git a/gui/fb/fbsup.h b/gui/fb/fbsup.h
index e39b644..a7d0944 100644
--- a/gui/fb/fbsup.h
+++ b/gui/fb/fbsup.h
@@ -197,7 +197,7 @@ private:
boost::shared_ptr<FBGlue> _glue;
/// This is the array of functioning input devices.
- std::vector<boost::shared_ptr<InputDevice> > _inputs;
+ std::vector<boost::shared_ptr<InputDevice> > _inputs;
boost::shared_ptr<Renderer> _renderer;
};
http://git.savannah.gnu.org/cgit//commit/?id=439d154a5eb8a9c72e58fc15fd18f0de004f8d37
commit 439d154a5eb8a9c72e58fc15fd18f0de004f8d37
Author: Rob Savoye <address@hidden>
Date: Fri Jan 21 17:23:11 2011 -0700
add evtest from freedesktop.org
diff --git a/libdevice/events/evtest.c b/libdevice/events/evtest.c
new file mode 100644
index 0000000..8460641
--- /dev/null
+++ b/libdevice/events/evtest.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 1999-2000 Vojtech Pavlik
+ * Copyright (c) 2009 Red Hat, Inc
+ *
+ * Event device test program
+ *
+ * See INSTALL for installation details or manually compile with
+ * gcc -o evtest evtest.c
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <address@hidden>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <stdint.h>
+
+#include <linux/version.h>
+#include <linux/input.h>
+
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#ifndef EV_SYN
+#define EV_SYN 0
+#endif
+
+char *events[EV_MAX + 1] = {
+ [0 ... EV_MAX] = NULL,
+ [EV_SYN] = "Sync", [EV_KEY] = "Key",
+ [EV_REL] = "Relative", [EV_ABS] = "Absolute",
+ [EV_MSC] = "Misc", [EV_LED] = "LED",
+ [EV_SND] = "Sound", [EV_REP] = "Repeat",
+ [EV_FF] = "ForceFeedback", [EV_PWR] = "Power",
+ [EV_FF_STATUS] = "ForceFeedbackStatus",
+};
+
+char *keys[KEY_MAX + 1] = {
+ [0 ... KEY_MAX] = NULL,
+ [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
+ [KEY_1] = "1", [KEY_2] = "2",
+ [KEY_3] = "3", [KEY_4] = "4",
+ [KEY_5] = "5", [KEY_6] = "6",
+ [KEY_7] = "7", [KEY_8] = "8",
+ [KEY_9] = "9", [KEY_0] = "0",
+ [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
+ [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
+ [KEY_Q] = "Q", [KEY_W] = "W",
+ [KEY_E] = "E", [KEY_R] = "R",
+ [KEY_T] = "T", [KEY_Y] = "Y",
+ [KEY_U] = "U", [KEY_I] = "I",
+ [KEY_O] = "O", [KEY_P] = "P",
+ [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
+ [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
+ [KEY_A] = "A", [KEY_S] = "S",
+ [KEY_D] = "D", [KEY_F] = "F",
+ [KEY_G] = "G", [KEY_H] = "H",
+ [KEY_J] = "J", [KEY_K] = "K",
+ [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
+ [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
+ [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
+ [KEY_Z] = "Z", [KEY_X] = "X",
+ [KEY_C] = "C", [KEY_V] = "V",
+ [KEY_B] = "B", [KEY_N] = "N",
+ [KEY_M] = "M", [KEY_COMMA] = "Comma",
+ [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
+ [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
+ [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
+ [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
+ [KEY_F2] = "F2", [KEY_F3] = "F3",
+ [KEY_F4] = "F4", [KEY_F5] = "F5",
+ [KEY_F6] = "F6", [KEY_F7] = "F7",
+ [KEY_F8] = "F8", [KEY_F9] = "F9",
+ [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
+ [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
+ [KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
+ [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
+ [KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
+ [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
+ [KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
+ [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
+ [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
+ [KEY_F11] = "F11", [KEY_F12] = "F12",
+ [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana",
+ [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan",
+ [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] =
"Muhenkan",
+ [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
+ [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
+ [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
+ [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
+ [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
+ [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
+ [KEY_END] = "End", [KEY_DOWN] = "Down",
+ [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
+ [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
+ [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown",
+ [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power",
+ [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] =
"KPPlusMinus",
+ [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma",
+ [KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja",
+ [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta",
+ [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose",
+ [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again",
+ [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo",
+ [KEY_FRONT] = "Front", [KEY_COPY] = "Copy",
+ [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste",
+ [KEY_FIND] = "Find", [KEY_CUT] = "Cut",
+ [KEY_HELP] = "Help", [KEY_MENU] = "Menu",
+ [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup",
+ [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp",
+ [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile",
+ [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer",
+ [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2",
+ [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS",
+ [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
+ [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail",
+ [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer",
+ [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward",
+ [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD",
+ [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong",
+ [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] =
"PreviousSong",
+ [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record",
+ [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone",
+ [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config",
+ [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh",
+ [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
+ [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
+ [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] =
"KPLeftParenthesis",
+ [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13",
+ [KEY_F14] = "F14", [KEY_F15] = "F15",
+ [KEY_F16] = "F16", [KEY_F17] = "F17",
+ [KEY_F18] = "F18", [KEY_F19] = "F19",
+ [KEY_F20] = "F20", [KEY_F21] = "F21",
+ [KEY_F22] = "F22", [KEY_F23] = "F23",
+ [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD",
+ [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
+ [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
+ [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
+ [KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost",
+ [KEY_PRINT] = "Print", [KEY_HP] = "HP",
+ [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
+ [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
+ [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
+ [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
+ [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
+ [KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel",
+ [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] =
"Brightness up",
+ [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
+ [BTN_0] = "Btn0", [BTN_1] = "Btn1",
+ [BTN_2] = "Btn2", [BTN_3] = "Btn3",
+ [BTN_4] = "Btn4", [BTN_5] = "Btn5",
+ [BTN_6] = "Btn6", [BTN_7] = "Btn7",
+ [BTN_8] = "Btn8", [BTN_9] = "Btn9",
+ [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
+ [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
+ [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
+ [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
+ [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
+ [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
+ [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
+ [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
+ [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
+ [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
+ [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
+ [BTN_B] = "BtnB", [BTN_C] = "BtnC",
+ [BTN_X] = "BtnX", [BTN_Y] = "BtnY",
+ [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
+ [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
+ [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
+ [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
+ [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
+ [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] =
"ToolRubber",
+ [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] =
"ToolPencil",
+ [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] =
"ToolFinger",
+ [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
+ [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
+ [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool
Doubletap",
+ [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_TOOL_QUADTAP] = "Tool
Quadtap",
+ [BTN_GEAR_DOWN] = "WheelBtn",
+ [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
+ [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
+ [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
+ [KEY_OPTION] = "Option", [KEY_INFO] = "Info",
+ [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor",
+ [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program",
+ [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites",
+ [KEY_EPG] = "EPG", [KEY_PVR] = "PVR",
+ [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language",
+ [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle",
+ [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom",
+ [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard",
+ [KEY_SCREEN] = "Screen", [KEY_PC] = "PC",
+ [KEY_TV] = "TV", [KEY_TV2] = "TV2",
+ [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2",
+ [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2",
+ [KEY_CD] = "CD", [KEY_TAPE] = "Tape",
+ [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner",
+ [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text",
+ [KEY_DVD] = "DVD", [KEY_AUX] = "Aux",
+ [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio",
+ [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory",
+ [KEY_LIST] = "List", [KEY_MEMO] = "Memo",
+ [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red",
+ [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow",
+ [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp",
+ [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First",
+ [KEY_LAST] = "Last", [KEY_AB] = "AB",
+ [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart",
+ [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle",
+ [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous",
+ [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN",
+ [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "Delete EOL",
+ [KEY_DEL_EOS] = "Delete EOS", [KEY_INS_LINE] = "Insert line",
+ [KEY_DEL_LINE] = "Delete line",
+ [KEY_VIDEOPHONE] = "Videophone", [KEY_GAMES] = "Games",
+ [KEY_ZOOMIN] = "Zoom In", [KEY_ZOOMOUT] = "Zoom Out",
+ [KEY_ZOOMRESET] = "Zoom Reset", [KEY_WORDPROCESSOR] = "Word
Processor",
+ [KEY_EDITOR] = "Editor", [KEY_SPREADSHEET] =
"Spreadsheet",
+ [KEY_GRAPHICSEDITOR] = "Graphics Editor", [KEY_PRESENTATION] =
"Presentation",
+ [KEY_DATABASE] = "Database", [KEY_NEWS] = "News",
+ [KEY_VOICEMAIL] = "Voicemail", [KEY_ADDRESSBOOK] =
"Addressbook",
+ [KEY_MESSENGER] = "Messenger", [KEY_DISPLAYTOGGLE] = "Display
Toggle",
+ [KEY_SPELLCHECK] = "Spellcheck", [KEY_LOGOFF] = "Log Off",
+ [KEY_DOLLAR] = "Dollar", [KEY_EURO] = "Euro",
+ [KEY_FRAMEBACK] = "Frame Back", [KEY_FRAMEFORWARD] = "Frame Forward",
+ [KEY_CONTEXT_MENU] = "Context Menu", [KEY_MEDIA_REPEAT] = "Media
Repeat",
+ [KEY_DEL_EOL] = "Delete EOL", [KEY_DEL_EOS] = "Delete EOS",
+ [KEY_INS_LINE] = "Insert Line", [KEY_DEL_LINE] = "Delete Line",
+ [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn Esc",
+ [KEY_FN_F1] = "Fn F1", [KEY_FN_F2] = "Fn F2",
+ [KEY_FN_F3] = "Fn F3", [KEY_FN_F4] = "Fn F4",
+ [KEY_FN_F5] = "Fn F5", [KEY_FN_F6] = "Fn F6",
+ [KEY_FN_F7] = "Fn F7", [KEY_FN_F8] = "Fn F8",
+ [KEY_FN_F9] = "Fn F9", [KEY_FN_F10] = "Fn F10",
+ [KEY_FN_F11] = "Fn F11", [KEY_FN_F12] = "Fn F12",
+ [KEY_FN_1] = "Fn 1", [KEY_FN_2] = "Fn 2",
+ [KEY_FN_D] = "Fn D", [KEY_FN_E] = "Fn E",
+ [KEY_FN_F] = "Fn F", [KEY_FN_S] = "Fn S",
+ [KEY_FN_B] = "Fn B",
+ [KEY_BRL_DOT1] = "Braille Dot 1", [KEY_BRL_DOT2] = "Braille Dot
2",
+ [KEY_BRL_DOT3] = "Braille Dot 3", [KEY_BRL_DOT4] = "Braille Dot
4",
+ [KEY_BRL_DOT5] = "Braille Dot 5", [KEY_BRL_DOT6] = "Braille Dot
6",
+ [KEY_BRL_DOT7] = "Braille Dot 7", [KEY_BRL_DOT8] = "Braille Dot
8",
+ [KEY_BRL_DOT9] = "Braille Dot 9", [KEY_BRL_DOT10] = "Braille Dot
10",
+ [KEY_NUMERIC_0] = "Numeric 0", [KEY_NUMERIC_1] = "Numeric 1",
+ [KEY_NUMERIC_2] = "Numeric 2", [KEY_NUMERIC_3] = "Numeric 3",
+ [KEY_NUMERIC_4] = "Numeric 4", [KEY_NUMERIC_5] = "Numeric 5",
+ [KEY_NUMERIC_6] = "Numeric 6", [KEY_NUMERIC_7] = "Numeric 7",
+ [KEY_NUMERIC_8] = "Numeric 8", [KEY_NUMERIC_9] = "Numeric 9",
+ [KEY_NUMERIC_STAR] = "Numeric *", [KEY_NUMERIC_POUND] = "Numeric
#",
+ [KEY_BATTERY] = "Battery",
+ [KEY_BLUETOOTH] = "Bluetooth", [KEY_BRIGHTNESS_CYCLE] =
"Brightness Cycle",
+ [KEY_BRIGHTNESS_ZERO] = "Brightness Zero", [KEY_DASHBOARD] =
"Dashboard",
+ [KEY_DISPLAY_OFF] = "Display Off", [KEY_DOCUMENTS] = "Documents",
+ [KEY_FORWARDMAIL] = "Forward Mail", [KEY_NEW] = "New",
+ [KEY_KBDILLUMDOWN] = "Kbd Illum Down", [KEY_KBDILLUMUP] = "Kbd Illum
Up",
+ [KEY_KBDILLUMTOGGLE] = "Kbd Illum Toggle", [KEY_REDO] = "Redo",
+ [KEY_REPLY] = "Reply", [KEY_SAVE] = "Save",
+ [KEY_SCALE] = "Scale", [KEY_SEND] = "Send",
+ [KEY_SCREENLOCK] = "Screen Lock", [KEY_SWITCHVIDEOMODE] = "Switch
Video Mode",
+ [KEY_UWB] = "UWB", [KEY_VIDEO_NEXT] = "Video Next",
+ [KEY_VIDEO_PREV] = "Video Prev", [KEY_WIMAX] = "WIMAX",
+ [KEY_WLAN] = "WLAN"
+
+};
+
+char *absval[6] = { "Value", "Min ", "Max ", "Fuzz ", "Flat ", "Resolution
"};
+
+char *relatives[REL_MAX + 1] = {
+ [0 ... REL_MAX] = NULL,
+ [REL_X] = "X", [REL_Y] = "Y",
+ [REL_Z] = "Z", [REL_HWHEEL] = "HWheel",
+ [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel",
+ [REL_MISC] = "Misc",
+};
+
+char *absolutes[ABS_MAX + 1] = {
+ [0 ... ABS_MAX] = NULL,
+ [ABS_X] = "X", [ABS_Y] = "Y",
+ [ABS_Z] = "Z", [ABS_RX] = "Rx",
+ [ABS_RY] = "Ry", [ABS_RZ] = "Rz",
+ [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder",
+ [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas",
+ [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X",
+ [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X",
+ [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X",
+ [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
+ [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
+ [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
+ [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
+ [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+ [ABS_MT_TOUCH_MAJOR] = "Touch Major",
+ [ABS_MT_TOUCH_MINOR] = "Touch Minor",
+ [ABS_MT_WIDTH_MAJOR] = "Width Major",
+ [ABS_MT_WIDTH_MINOR] = "Width Minor",
+ [ABS_MT_ORIENTATION] = "Orientation",
+ [ABS_MT_POSITION_X] = "Position X",
+ [ABS_MT_POSITION_Y] = "Position Y",
+ [ABS_MT_TOOL_TYPE] = "Tool Type",
+ [ABS_MT_BLOB_ID] = "Blob ID",
+ [ABS_MT_TRACKING_ID] = "Tracking ID",
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ [ABS_MT_PRESSURE] = "Pressure",
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+ [ABS_MT_SLOT] = "Slot",
+#endif
+
+};
+
+char *misc[MSC_MAX + 1] = {
+ [ 0 ... MSC_MAX] = NULL,
+ [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
+ [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData",
+ [MSC_SCAN] = "ScanCode",
+};
+
+char *leds[LED_MAX + 1] = {
+ [0 ... LED_MAX] = NULL,
+ [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
+ [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
+ [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
+ [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute",
+ [LED_MISC] = "Misc",
+};
+
+char *repeats[REP_MAX + 1] = {
+ [0 ... REP_MAX] = NULL,
+ [REP_DELAY] = "Delay", [REP_PERIOD] = "Period"
+};
+
+char *sounds[SND_MAX + 1] = {
+ [0 ... SND_MAX] = NULL,
+ [SND_CLICK] = "Click", [SND_BELL] = "Bell",
+ [SND_TONE] = "Tone"
+};
+
+char **names[EV_MAX + 1] = {
+ [0 ... EV_MAX] = NULL,
+ [EV_SYN] = events, [EV_KEY] = keys,
+ [EV_REL] = relatives, [EV_ABS] = absolutes,
+ [EV_MSC] = misc, [EV_LED] = leds,
+ [EV_SND] = sounds, [EV_REP] = repeats,
+};
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define BIT(x) (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
+
+int main (int argc, char **argv)
+{
+ int fd, rd, i, j, k;
+ struct input_event ev[64];
+ int version;
+ unsigned short id[4];
+ unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
+ char name[256] = "Unknown";
+ int abs[6] = {0};
+
+ if (argc < 2) {
+ printf("Usage: evtest /dev/input/eventX\n");
+ printf("Where X = input device number\n");
+ return 1;
+ }
+
+ if ((fd = open(argv[argc - 1], O_RDONLY)) < 0) {
+ perror("evtest");
+ return 1;
+ }
+
+ if (ioctl(fd, EVIOCGVERSION, &version)) {
+ perror("evtest: can't get version");
+ return 1;
+ }
+
+ printf("Input driver version is %d.%d.%d\n",
+ version >> 16, (version >> 8) & 0xff, version & 0xff);
+
+ ioctl(fd, EVIOCGID, id);
+ printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version
0x%x\n",
+ id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);
+
+ ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+ printf("Input device name: \"%s\"\n", name);
+
+ memset(bit, 0, sizeof(bit));
+ ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
+ printf("Supported events:\n");
+
+ for (i = 0; i < EV_MAX; i++)
+ if (test_bit(i, bit[0])) {
+ printf(" Event type %d (%s)\n", i, events[i] ?
events[i] : "?");
+ if (!i) continue;
+ ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
+ for (j = 0; j < KEY_MAX; j++)
+ if (test_bit(j, bit[i])) {
+ printf(" Event code %d (%s)\n", j,
names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
+ if (i == EV_ABS) {
+ ioctl(fd, EVIOCGABS(j), abs);
+ for (k = 0; k < 6; k++)
+ if ((k < 3) || abs[k])
+ printf("
%s %6d\n", absval[k], abs[k]);
+ }
+ }
+ }
+
+
+ printf("Testing ... (interrupt to exit)\n");
+
+ while (1) {
+ rd = read(fd, ev, sizeof(struct input_event) * 64);
+
+ if (rd < (int) sizeof(struct input_event)) {
+ printf("yyy\n");
+ perror("\nevtest: error reading");
+ return 1;
+ }
+
+ for (i = 0; i < rd / sizeof(struct input_event); i++)
+
+ if (ev[i].type == EV_SYN) {
+ printf("Event: time %ld.%06ld, --------------
%s ------------\n",
+ ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].code ? "Config Sync" : "Report Sync" );
+ } else if (ev[i].type == EV_MSC && (ev[i].code ==
MSC_RAW || ev[i].code == MSC_SCAN)) {
+ printf("Event: time %ld.%06ld, type %d (%s),
code %d (%s), value %02x\n",
+ ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type,
+ events[ev[i].type] ? events[ev[i].type]
: "?",
+ ev[i].code,
+ names[ev[i].type] ?
(names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
+ ev[i].value);
+ } else {
+ printf("Event: time %ld.%06ld, type %d (%s),
code %d (%s), value %d\n",
+ ev[i].time.tv_sec, ev[i].time.tv_usec,
ev[i].type,
+ events[ev[i].type] ? events[ev[i].type]
: "?",
+ ev[i].code,
+ names[ev[i].type] ?
(names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
+ ev[i].value);
+ }
+
+ }
+}
http://git.savannah.gnu.org/cgit//commit/?id=e2337eac41e0802575dc72a0194a4e0ac7a68642
commit e2337eac41e0802575dc72a0194a4e0ac7a68642
Author: Rob Savoye <address@hidden>
Date: Wed Jan 19 21:19:42 2011 -0700
reset input devices to no, or we can't select just one
diff --git a/configure.ac b/configure.ac
index b9c8e1d..5a9d339 100644
--- a/configure.ac
+++ b/configure.ac
@@ -853,6 +853,10 @@ AC_ARG_ENABLE(input,
[if test -n ${enableval}; then
enableval=`echo ${enableval} | tr '\054' ' ' `
fi
+ build_ps2mouse=no
+ build_ps2keyboard=no
+ build_input_events=no
+ build_tslib=no
while test -n "${enableval}" ; do
val=`echo ${enableval} | cut -d ' ' -f 1`
case "${val}" in
-----------------------------------------------------------------------
Summary of changes:
configure.ac | 4 +
gui/fb/fb.cpp | 59 +-
gui/fb/fbsup.h | 2 +-
libdevice/events/EventDevice.cpp | 180 +++-
libdevice/events/InputDevice.cpp | 30 +-
libdevice/events/InputDevice.h | 30 +-
libdevice/events/MouseDevice.cpp | 30 +-
libdevice/events/TouchDevice.cpp | 23 +-
libdevice/events/events.am | 10 +-
libdevice/events/evtest.c | 463 ++++++++++
libdevice/events/test_events.cpp | 4 +-
librender/agg/Renderer_agg.cpp | 1842 ++++++++++++++++++--------------------
12 files changed, 1640 insertions(+), 1037 deletions(-)
create mode 100644 libdevice/events/evtest.c
hooks/post-receive
--
Gnash
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] [SCM] Gnash branch, openvg, updated. 516fc91dd2bbb638ac6a5e632772f0a0ad9288cc,
Rob Savoye <=