summaryrefslogtreecommitdiffstats
path: root/libdimensionxx
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-04-12 19:06:50 +0000
committerTavian Barnes <tavianator@gmail.com>2009-04-12 19:06:50 +0000
commitb9e19e076662ae5743b9c81eb238fe11204f6dbd (patch)
tree2a29279adf20a2b8291f56f341695db07e861e98 /libdimensionxx
parent8a4f9e902cf64f97ee2f15fa3940a7cf183a27b7 (diff)
downloaddimension-b9e19e076662ae5743b9c81eb238fe11204f6dbd.tar.xz
Add some comments.
Diffstat (limited to 'libdimensionxx')
-rw-r--r--libdimensionxx/canvas.cpp51
-rw-r--r--libdimensionxx/color.cpp1
-rw-r--r--libdimensionxx/cookie.cpp50
-rw-r--r--libdimensionxx/dimensionxx/canvas.hpp32
-rw-r--r--libdimensionxx/dimensionxx/color.hpp13
-rw-r--r--libdimensionxx/dimensionxx/cookie.hpp3
-rw-r--r--libdimensionxx/dimensionxx/error.hpp8
-rw-r--r--libdimensionxx/dimensionxx/geometry.hpp15
-rw-r--r--libdimensionxx/dimensionxx/png.hpp20
-rw-r--r--libdimensionxx/error.cpp3
-rw-r--r--libdimensionxx/png.cpp19
11 files changed, 190 insertions, 25 deletions
diff --git a/libdimensionxx/canvas.cpp b/libdimensionxx/canvas.cpp
index 2340066..411d4e8 100644
--- a/libdimensionxx/canvas.cpp
+++ b/libdimensionxx/canvas.cpp
@@ -22,8 +22,59 @@
namespace Dimension
{
+ // Allocate the canvas with dmnsn_new_canvas()
+ Canvas::Canvas(unsigned int width, unsigned int height)
+ : m_canvas(dmnsn_new_canvas(width, height)) { }
+
+ // Virtual destructor: delete the canvas with dmnsn_delete_canvas().
Canvas::~Canvas()
{
dmnsn_delete_canvas(m_canvas);
}
+
+ // Get the width
+ unsigned int
+ Canvas::width() const
+ {
+ return m_canvas->x;
+ }
+
+ // Get the height
+ unsigned int
+ Canvas::height() const
+ {
+ return m_canvas->y;
+ }
+
+ // Get a particular pixel, thread-safely, with dmnsn_get_pixel().
+ Color
+ Canvas::pixel(unsigned int x, unsigned int y) const
+ {
+ return Color(dmnsn_get_pixel(m_canvas, x, y));
+ }
+
+ // Set a particular pixel, thread-safely, with dmnsn_set_pixel().
+ void
+ Canvas::pixel(unsigned int x, unsigned int y, const Color& c)
+ {
+ dmnsn_set_pixel(m_canvas, x, y, c.dmnsn());
+ }
+
+ // Return the wrapped canvas
+ dmnsn_canvas*
+ Canvas::dmnsn()
+ {
+ return m_canvas;
+ }
+
+ // Return a const version of the wrapped canvas
+ const dmnsn_canvas*
+ Canvas::dmnsn() const
+ {
+ return m_canvas;
+ }
+
+ // Protected default constructor: set m_canvas to NULL.
+ Canvas::Canvas()
+ : m_canvas(0) { }
}
diff --git a/libdimensionxx/color.cpp b/libdimensionxx/color.cpp
index c7f768a..ffbc808 100644
--- a/libdimensionxx/color.cpp
+++ b/libdimensionxx/color.cpp
@@ -22,5 +22,6 @@
namespace Dimension
{
+ // Definition of whitepoint
const CIE_XYZ whitepoint(dmnsn_whitepoint);
}
diff --git a/libdimensionxx/cookie.cpp b/libdimensionxx/cookie.cpp
index dd8a06d..c3b1541 100644
--- a/libdimensionxx/cookie.cpp
+++ b/libdimensionxx/cookie.cpp
@@ -21,10 +21,20 @@
#include "dimensionxx.hpp"
#include <stdio.h>
+// The conundrum: libdimension and libdimension-* use C I/O, with FILE*'s.
+// We want to use C++ I/O with std::i/ostreams. Unfortunately, there's no
+// standard way to map between them, so we use the nonportable GNU stdio
+// extension fopencookie(), which creates a FILE* with custom read/write/seek
+// functions. BSD also has a similar function, funopen(), which we should
+// use too. Failing in all that, we should fall back on a tmpfile() buffer,
+// but that would require an fclosecookie() function as well, to copy the
+// buffer to the stream potentially.
+
namespace Dimension
{
namespace
{
+ // Internal cookie type to hold the C++ streams.
struct Cookie
{
public:
@@ -32,43 +42,50 @@ namespace Dimension
std::ostream* ostr;
};
+ // Cookie read function
ssize_t
cookie_read(void* cookie, char* buf, size_t size)
{
Cookie* streams = reinterpret_cast<Cookie*>(cookie);
+ // Do the unformatted read
streams->istr->read(buf, size);
- if (streams->istr->eof()) {
- return streams->istr->gcount();
- } else if (!streams->istr->good()) {
- return -1;
+ if (streams->istr->eof() || streams->istr->good()) {
+ return streams->istr->gcount(); // This returns 0 on an immediate EOF
+ // for us.
} else {
- return streams->istr->gcount();
+ // Some non-EOF error
+ return -1;
}
}
+ // Cookie write function
ssize_t
cookie_write(void* cookie, const char* buf, size_t size)
{
Cookie* streams = reinterpret_cast<Cookie*>(cookie);
+ // Do the unformatted write
streams->ostr->write(buf, size);
- if (!streams->ostr->good()) {
- return -1;
- } else {
+ if (streams->ostr->good()) {
+ // Write operation succeeded, so we must've written size bytes
return size;
+ } else {
+ // Write operation failed
+ return -1;
}
}
+ // Cookie seek function
int
cookie_seek(void* cookie, off64_t* offset, int whence)
{
Cookie* streams = reinterpret_cast<Cookie*>(cookie);
- bool success = true;
if (streams->istr) {
+ // If we have an input stream, seek it
switch (whence) {
case SEEK_SET:
streams->istr->seekg(*offset, std::ios::beg);
@@ -82,11 +99,13 @@ namespace Dimension
}
if (!streams->istr->good()) {
- success = false;
+ // Seek failed
+ return 1;
}
}
if (streams->ostr) {
+ // If we have an output stream, seek it too
switch (whence) {
case SEEK_SET:
streams->ostr->seekp(*offset, std::ios::beg);
@@ -99,20 +118,25 @@ namespace Dimension
}
if (!streams->ostr->good()) {
- success = false;
+ // Seek failed
+ return 1;
}
}
- return !success;
+ // Seek succeeded
+ return 0;
}
+ // Cookie delete function
int
cookie_close(void* cookie)
{
+ // Free the cookie
delete reinterpret_cast<Cookie*>(cookie);
}
}
+ // Make an input FILE*
std::FILE*
fcookie(std::istream& istr)
{
@@ -129,6 +153,7 @@ namespace Dimension
return fopencookie(reinterpret_cast<void*>(cookie), "r", io_funcs);
}
+ // Make an output FILE*
std::FILE*
fcookie(std::ostream& ostr)
{
@@ -145,6 +170,7 @@ namespace Dimension
return fopencookie(reinterpret_cast<void*>(cookie), "w", io_funcs);
}
+ // Make an I/O FILE*
std::FILE*
fcookie(std::iostream& iostr)
{
diff --git a/libdimensionxx/dimensionxx/canvas.hpp b/libdimensionxx/dimensionxx/canvas.hpp
index c501413..eda9ad3 100644
--- a/libdimensionxx/dimensionxx/canvas.hpp
+++ b/libdimensionxx/dimensionxx/canvas.hpp
@@ -21,29 +21,39 @@
#ifndef DIMENSIONXX_CANVAS_HPP
#define DIMENSIONXX_CANVAS_HPP
+// dmnsn_canvas* wrapper.
+
namespace Dimension
{
+ // Base canvas class. Wraps a dmnsn_canvas*.
class Canvas
{
public:
- Canvas(unsigned int width, unsigned int height)
- : m_canvas(dmnsn_new_canvas(width, height)) { }
+ // Allocate a dmnsn_canvas specified width and height.
+ Canvas(unsigned int width, unsigned int height);
+
+ // Wrap an existing canvas.
explicit Canvas(dmnsn_canvas* canvas) : m_canvas(canvas) { }
+
+ // Delete the canvas. (dmnsn_delete_canvas(m_canvas).)
virtual ~Canvas();
- unsigned int width() const { return m_canvas->x; }
- unsigned int height() const { return m_canvas->y; }
+ // Get the width and height.
+ unsigned int width() const;
+ unsigned int height() const;
- Color pixel(unsigned int x, unsigned int y) const
- { return Color(dmnsn_get_pixel(m_canvas, x, y)); }
- void pixel(unsigned int x, unsigned int y, const Color& c)
- { dmnsn_set_pixel(m_canvas, x, y, c.dmnsn()); }
+ // Get and set a pixel, thread-safely.
+ Color pixel(unsigned int x, unsigned int y) const;
+ void pixel(unsigned int x, unsigned int y, const Color& c);
- dmnsn_canvas* dmnsn() { return m_canvas; }
- const dmnsn_canvas* dmnsn() const { return m_canvas; }
+ // Access the wrapped C object.
+ dmnsn_canvas* dmnsn();
+ const dmnsn_canvas* dmnsn() const;
protected:
- Canvas() : m_canvas(0) { }
+ // Derived classes may want to set m_canvas later. Set it to NULL now, so
+ // that the destructor can still dmnsn_delete_canvas it.
+ Canvas();
dmnsn_canvas* m_canvas;
diff --git a/libdimensionxx/dimensionxx/color.hpp b/libdimensionxx/dimensionxx/color.hpp
index afd7ea5..a7087a7 100644
--- a/libdimensionxx/dimensionxx/color.hpp
+++ b/libdimensionxx/dimensionxx/color.hpp
@@ -21,16 +21,21 @@
#ifndef DIMENSIONXX_COLOR_HPP
#define DIMENSIONXX_COLOR_HPP
+// Wrappers for libdimension colors.
+
namespace Dimension
{
+ // Forward declarations
class CIE_XYZ;
class CIE_xyY;
class CIE_Lab;
class CIE_Luv;
class sRGB;
+ // Default whitepoint (D50)
extern const CIE_XYZ whitepoint;
+ // Wrapper for dmnsn_color
class Color
{
public:
@@ -44,6 +49,7 @@ namespace Dimension
// Color(const Color& c);
// ~Color();
+ // Get and set filtered and unfiltered transparancy
double filter() const { return m_color.filter; }
double trans() const { return m_color.trans; }
@@ -51,15 +57,20 @@ namespace Dimension
double trans(double t) { m_color.trans = t; }
// Color& operator=(const Color& c);
+
+ // Add a color to this one in a perceptually correct manner
Color& operator+=(const Color& c)
{ m_color = dmnsn_color_add(m_color, c.m_color); return *this; }
+ // Access the wrapped color
dmnsn_color dmnsn() const { return m_color; }
private:
dmnsn_color m_color;
};
+ // Wrappers for all libdimension color types
+
class CIE_XYZ
{
public:
@@ -206,6 +217,7 @@ namespace Dimension
// Color operators
+ // Perceptually correct color combination
inline Color
operator+(const Color& lhs, const Color& rhs)
{
@@ -214,6 +226,7 @@ namespace Dimension
return temp;
}
+ // Perceptual color difference
inline double
operator-(const Color& lhs, const Color& rhs)
{
diff --git a/libdimensionxx/dimensionxx/cookie.hpp b/libdimensionxx/dimensionxx/cookie.hpp
index acb783d..639fbfe 100644
--- a/libdimensionxx/dimensionxx/cookie.hpp
+++ b/libdimensionxx/dimensionxx/cookie.hpp
@@ -21,6 +21,9 @@
#ifndef DIMENSIONXX_COOKIE_HPP
#define DIMENSIONXX_COOKIE_HPP
+// Some internal magic to use C FILE* I/O with C++ streams. Currently this ties
+// us to Linux and glibc, but in the future, this will be portable.
+
#include <istream>
#include <ostream>
#include <cstdio>
diff --git a/libdimensionxx/dimensionxx/error.hpp b/libdimensionxx/dimensionxx/error.hpp
index 8919895..99670cb 100644
--- a/libdimensionxx/dimensionxx/error.hpp
+++ b/libdimensionxx/dimensionxx/error.hpp
@@ -21,21 +21,29 @@
#ifndef DIMENSIONXX_ERROR_HPP
#define DIMENSIONXX_ERROR_HPP
+// Wrappers for libdimension error handling, and an exception class.
+// dmnsn_error is still used by libdimensionxx whenever an exception shouldn't
+// be thrown, like in destructors, and whenever libdimension or libdimension-*
+// use it internally. Exceptions are thrown otherwise to report errors.
+
#include <dimension.h>
#include <stdexcept>
#include <string>
namespace Dimension
{
+ // Wrapper for dmnsn_severity
enum Severity {
SEVERITY_LOW = DMNSN_SEVERITY_LOW,
SEVERITY_MEDIUM = DMNSN_SEVERITY_MEDIUM,
SEVERITY_HIGH = DMNSN_SEVERITY_HIGH
};
+ // Get or set the resilience, thread-safely
Severity resilience();
void resilience(Severity resilience);
+ // Generic exception class, derives from std::runtime_error
class Dimension_Error : public std::runtime_error
{
public:
diff --git a/libdimensionxx/dimensionxx/geometry.hpp b/libdimensionxx/dimensionxx/geometry.hpp
index 4295c05..78b9b49 100644
--- a/libdimensionxx/dimensionxx/geometry.hpp
+++ b/libdimensionxx/dimensionxx/geometry.hpp
@@ -21,12 +21,15 @@
#ifndef DIMENSIONXX_GEOMETRY_HPP
#define DIMENSIONXX_GEOMETRY_HPP
+// Wrappers for geometric types (Scalars, Vectors, Lines (rays)).
+
#include <dimension.h>
namespace Dimension
{
- typedef dmnsn_scalar Scalar;
+ typedef dmnsn_scalar Scalar; // This is really `double'
+ // Wrapper for dmnsn_vector
class Vector
{
public:
@@ -37,10 +40,13 @@ namespace Dimension
// Vector(const Vector& v);
// ~Vector();
+ // Get the x, y, and z components.
Scalar x() const { return m_vector.x; }
Scalar y() const { return m_vector.y; }
Scalar z() const { return m_vector.z; }
+ // Vector arithmetic
+
// Vector& operator=(const Vector& rhs);
Vector& operator+=(const Vector& rhs)
{ m_vector = dmnsn_vector_add(m_vector, rhs.m_vector); return *this; }
@@ -51,12 +57,14 @@ namespace Dimension
Vector& operator/=(Scalar rhs)
{ m_vector = dmnsn_vector_div(m_vector, rhs); return *this; }
+ // Get the wrapped vector
dmnsn_vector dmnsn() const { return m_vector; }
private:
dmnsn_vector m_vector;
};
+ // Wrapper for dmnsn_line
class line
{
public:
@@ -70,8 +78,11 @@ namespace Dimension
Vector n() const { return Vector(m_line.n); }
// line& operator=(const line& l);
+
+ // Get the point `t' on the line (x0 + t*n)
Vector operator()(Scalar t) { return Vector(dmnsn_line_point(m_line, t)); }
+ // Get the wrapped line
dmnsn_line dmnsn() const { return m_line; }
private:
@@ -120,12 +131,14 @@ namespace Dimension
return r;
}
+ // Dot product
inline Scalar
dot(const Vector& lhs, const Vector& rhs)
{
return dmnsn_vector_dot(lhs.dmnsn(), rhs.dmnsn());
}
+ // Cross product
inline Vector
cross(const Vector& lhs, const Vector& rhs)
{
diff --git a/libdimensionxx/dimensionxx/png.hpp b/libdimensionxx/dimensionxx/png.hpp
index 96ab2ca..c14b25f 100644
--- a/libdimensionxx/dimensionxx/png.hpp
+++ b/libdimensionxx/dimensionxx/png.hpp
@@ -21,25 +21,43 @@
#ifndef DIMENSIONXX_PNG_HPP
#define DIMENSIONXX_PNG_HPP
+// C++ wrapper for libdimension-png. PNG_Canvas derives from Canvas.
+
#include <istream>
#include <ostream>
namespace Dimension
{
+ // PNG_Canvas handles reading a Canvas from a PNG file, writing one to a PNG
+ // file, or both, depending on what type of stream(s) are given to the
+ // constructor.
class PNG_Canvas : public Canvas
{
public:
+ // Input PNG_Canvas; read the Canvas from istr now
explicit PNG_Canvas(std::istream& istr)
: Canvas(), m_istr(&istr), m_ostr(0), m_written(false) { read(); }
+
+ // Output PNG_Canvas; write the Canvas to ostr at destruction, or when
+ // write() is called.
PNG_Canvas(unsigned int x, unsigned int y, std::ostream& ostr)
: Canvas(x, y), m_istr(0), m_ostr(&ostr), m_written(false) { }
+
+ // I/O PNG_Canvas; read the Canvas from istr now, and write to ostr at
+ // destruction or then write() is called.
PNG_Canvas(std::istream& istr, std::ostream& ostr)
: Canvas(), m_istr(&istr), m_ostr(&ostr), m_written(false) { read(); }
+
+ // Call write() if we're an output PNG_Canvas, but trap any exceptions and
+ // report a dmnsn_error() instead.
virtual ~PNG_Canvas();
+ // Write the Canvas to the output stream, throwing a Dimension_Error on
+ // error.
void write();
protected:
+ // In case a derived class needs to set m_canvas after we're constructed
PNG_Canvas(std::ostream* ostr)
: Canvas(), m_istr(0), m_ostr(ostr), m_written(false) { }
@@ -48,6 +66,8 @@ namespace Dimension
std::ostream* m_ostr;
bool m_written;
+ // Read the Canvas from a PNG file, and throw a Dimension_Error upon
+ // failure.
void read();
// Copying prohibited
diff --git a/libdimensionxx/error.cpp b/libdimensionxx/error.cpp
index 948a8c0..3d7dfa0 100644
--- a/libdimensionxx/error.cpp
+++ b/libdimensionxx/error.cpp
@@ -24,18 +24,21 @@
namespace Dimension
{
+ // Get the resilience, thread-safely, with dmnsn_get_resilience().
Severity
resilience()
{
return static_cast<Severity>(dmnsn_get_resilience());
}
+ // Set the resilience, thread-safely, with dmnsn_set_resilience().
void
resilience(Severity resilience)
{
dmnsn_set_resilience(static_cast<dmnsn_severity>(resilience));
}
+ // Dimension_Error constructor
Dimension_Error::Dimension_Error(const std::string& str)
: std::runtime_error(str) { }
}
diff --git a/libdimensionxx/png.cpp b/libdimensionxx/png.cpp
index 1ca3047..348b7a7 100644
--- a/libdimensionxx/png.cpp
+++ b/libdimensionxx/png.cpp
@@ -25,6 +25,9 @@
namespace Dimension
{
+ // PNG_Canvas destructor. Call write() to write the PNG file if not already
+ // written, but catch any exceptions and instead report the error with
+ // dmnsn_error() to avoid throwing from a destructor.
PNG_Canvas::~PNG_Canvas()
{
if (m_ostr && !m_written) {
@@ -37,46 +40,60 @@ namespace Dimension
}
}
+ // Write the PNG file. Uses the fcookie() interface to make a FILE*
+ // corresponding to an std::ostream (including std::ostringstream, etc).
void PNG_Canvas::write()
{
if (m_written) {
+ // Does writing a PNG file twice make sense?
throw Dimension_Error("Attempt to write canvas to PNG twice.");
}
if (!m_ostr) {
+ // Don't call write() if we're not an output PNG_Canvas...
throw Dimension_Error("Attempt to write canvas to PNG without an output"
" stream.");
}
FILE* file = fcookie(*m_ostr);
if (!file) {
+ // fcookie() shouldn't fail, really
throw Dimension_Error("Couldn't create C++/C IO interface when writing"
" canvas to PNG.");
}
+ // Write the PNG file
if (dmnsn_png_write_canvas(m_canvas, file)) {
+ // The actual write operation failed, for some reason.
std::fclose(file);
throw Dimension_Error("Writing canvas to PNG failed.");
}
std::fclose(file);
- m_written = true;
+ m_written = true; // We've written the file now, don't do it again
}
+ // Read a canvas from a PNG file. Uses the fcookie() interface to make a
+ // FILE* corresponding to an std::istream (including std::istringstream, etc).
void PNG_Canvas::read()
{
if (!m_istr) {
+ // read() is private, and only called from the appropriate constructors,
+ // so this REALLY shouldn't happen.
throw Dimension_Error("Attempt to read canvas from PNG without an input"
" stream.");
}
FILE* file = fcookie(*m_istr);
if (!file) {
+ // fcookie() shouldn't fail, really
throw Dimension_Error("Couldn't create C++/C IO interface when reading"
" canvas from PNG.");
}
+ // Read the canvas from a PNG file
if (!(m_canvas = dmnsn_png_read_canvas(file))) {
+ // The read operation failed
std::fclose(file);
throw Dimension_Error("Reading canvas from PNG failed.");
}