annotate src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc @ 611:0fbaf443ec82

Carfac C++ revision 3, indluding more style improvements. The output structs are now classes again, and have separate storage methods for each output structure along with flags in the Run and RunSegment methods to allow for only storing NAPs if desired.
author alexbrandmeyer
date Fri, 17 May 2013 19:52:45 +0000
parents dd0448d4ab69
children
rev   line source
tomwalters@237 1 // Copyright 2007-2010, Thomas Walters, Willem van Engen
tomwalters@116 2 //
tomwalters@116 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@116 4 // http://www.acousticscale.org/AIMC
tomwalters@116 5 //
tomwalters@116 6 // Licensed under the Apache License, Version 2.0 (the "License");
tomwalters@116 7 // you may not use this file except in compliance with the License.
tomwalters@116 8 // You may obtain a copy of the License at
tomwalters@116 9 //
tomwalters@116 10 // http://www.apache.org/licenses/LICENSE-2.0
tomwalters@116 11 //
tomwalters@116 12 // Unless required by applicable law or agreed to in writing, software
tomwalters@116 13 // distributed under the License is distributed on an "AS IS" BASIS,
tomwalters@116 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
tomwalters@116 15 // See the License for the specific language governing permissions and
tomwalters@116 16 // limitations under the License.
tomwalters@116 17
tomwalters@116 18 /*!
tomwalters@116 19 * \file
tomwalters@116 20 * \brief Output device for output to a graphics file using cairo (LGPL)
tomwalters@116 21 *
tomwalters@116 22 * \author Tom Walters <tom@acousticscale.org> and Willem van Engen <cnbh@willem.engen.nl>
tomwalters@116 23 * \date created 2007/09/17
tomwalters@116 24 * \version \$Header: $
tomwalters@116 25 */
tomwalters@116 26
tomwalters@116 27 #include "Support/Common.h"
tomwalters@116 28
tomwalters@116 29 #include <sys/types.h>
tomwalters@116 30 #include <sys/stat.h>
tomwalters@116 31 #include <string.h>
tomwalters@116 32 #include <stdio.h>
tomwalters@116 33 #include <math.h>
tomwalters@238 34 #include <limits.h>
tomwalters@116 35
tomwalters@257 36 #ifdef _WINDOWS
tomwalters@257 37 # include <direct.h> // for _mkdir&_rmdir
tomwalters@258 38 #endif
tomwalters@257 39
tomwalters@238 40 //#include "cairo-quartz.h"
tomwalters@237 41
tom@229 42 #include "Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.h"
tom@229 43
tom@229 44 namespace aimc {
tomwalters@116 45
tomwalters@116 46 GraphicsOutputDeviceCairo::GraphicsOutputDeviceCairo(Parameters *pParam)
tom@229 47 : GraphicsOutputDevice(pParam) {
tomwalters@228 48 m_bOutputFile = false;
tomwalters@228 49 m_iFileNumber = 0;
tomwalters@228 50 m_iVertexType = VertexTypeNone;
tomwalters@228 51 m_bUseMemoryBuffer=false;
tomwalters@256 52 parameters_->DefaultString("output.img.format", "png");
tomwalters@256 53 }
tomwalters@256 54
tomwalters@256 55 void GraphicsOutputDeviceCairo::Reset(Parameters* global_parameters) {
tomwalters@256 56 Initialize(global_parameters);
tomwalters@256 57 }
tomwalters@256 58
tomwalters@256 59 bool GraphicsOutputDeviceCairo::Initialize(Parameters *global_parameters) {
tomwalters@256 60 global_parameters_ = global_parameters;
tomwalters@256 61 #ifdef _WINDOWS
tomwalters@256 62 string pathsep("\\");
tomwalters@256 63 #else
tomwalters@256 64 string pathsep("/");
tomwalters@256 65 #endif
tomwalters@256 66 directory_ = global_parameters->GetString("output_filename_base") + pathsep;
tomwalters@256 67 //! \todo Make build system check for mkdtemp() to use it when available. See TODO.txt.
tomwalters@256 68 #ifdef _WINDOWS
tomwalters@259 69 _mkdir(directory_.c_str());
tomwalters@256 70 #else
tomwalters@256 71 mkdir(directory_.c_str(), S_IRWXU);
tomwalters@256 72 #endif
tomwalters@256 73 InitialzeInternal();
tomwalters@256 74 return true;
tomwalters@145 75 }
tomwalters@145 76
tomwalters@237 77 bool GraphicsOutputDeviceCairo::Initialize(string directory) {
tomwalters@237 78 directory_ = directory;
tomwalters@256 79 InitialzeInternal();
tomwalters@227 80
tomwalters@228 81 /* Try to open an image to see if everything is allright. We want to avoid
tomwalters@228 82 * errors in the main Process()ing loop. */
tomwalters@237 83 /*if (!OpenFile(0)) {
tomwalters@228 84 //! \todo Better error message that is more specific about the cause.
tom@230 85 LOG_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."),
tomwalters@237 86 directory_.c_str(), parameters_->DefaultString("output.img.format", "png"));
tomwalters@228 87 return false;
tomwalters@228 88 }
tomwalters@237 89 CloseFile();*/
tomwalters@227 90
tomwalters@228 91 return true;
tomwalters@145 92 }
tomwalters@145 93
tomwalters@237 94 /*bool GraphicsOutputDeviceCairo::Initialize() {
tomwalters@116 95 Init();
tomwalters@116 96 m_bUseMemoryBuffer = true;
tomwalters@116 97 return(true);
tomwalters@237 98 }*/
tomwalters@116 99
tomwalters@256 100 void GraphicsOutputDeviceCairo::InitialzeInternal() {
tomwalters@237 101 AIM_ASSERT(parameters_);
tomwalters@116 102
tomwalters@237 103 parameters_->DefaultString("output.img.color.background", "black");
tomwalters@116 104
tomwalters@237 105 m_bInvertColors = parameters_->DefaultBool("output.img.color.invert", "false");
tomwalters@237 106
tomwalters@237 107 // Output size.
tomwalters@237 108 m_iWidth = parameters_->DefaultInt("output.img.width", 800);
tomwalters@237 109 m_iHeight = parameters_->DefaultInt("output.img.height", 600);
tomwalters@237 110
tomwalters@237 111 // Cairo's RGB24 format has 32-bit pixels with the upper 8 bits unused.
tomwalters@237 112 // This is not the same as the plotutils PNG format. This information is transferred by the
tomwalters@237 113 // function GetPixelFormat. The pixel format is dealt with by the reciever.
tomwalters@238 114 m_cSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
tomwalters@237 115 m_iWidth,
tomwalters@237 116 m_iHeight);
tomwalters@237 117 m_cCr = cairo_create(m_cSurface);
tomwalters@237 118 cairo_scale(m_cCr, (float)m_iWidth, (float)m_iHeight);
tomwalters@237 119 // Now setup things for this plotter.
tomwalters@237 120 cairo_select_font_face(m_cCr,
tomwalters@237 121 parameters_->DefaultString("output.img.fontname",
tomwalters@237 122 "HersheySans"),
tomwalters@237 123 CAIRO_FONT_SLANT_NORMAL,
tomwalters@237 124 CAIRO_FONT_WEIGHT_BOLD);
tomwalters@237 125 cairo_set_font_size (m_cCr, 0.02);
tomwalters@116 126 }
tomwalters@116 127
tomwalters@116 128 unsigned char* GraphicsOutputDeviceCairo::GetBuffer() {
tomwalters@116 129 if(m_bUseMemoryBuffer)
tomwalters@116 130 return (cairo_image_surface_get_data (m_cSurface));
tomwalters@116 131 else
tomwalters@116 132 return NULL;
tomwalters@116 133 }
tomwalters@116 134
tomwalters@116 135 bool GraphicsOutputDeviceCairo::OpenFile(unsigned int index) {
tomwalters@237 136 const char *strPlottype = parameters_->GetString("output.img.format");
tomwalters@116 137 if (!m_bUseMemoryBuffer) {
tomwalters@116 138 struct stat fileinfo;
tomwalters@116 139 // Get filename without trailing slash
tomwalters@237 140 char filename[PATH_MAX];
tomwalters@237 141 strncpy(filename, directory_.c_str(), sizeof(filename)/sizeof(filename[0]));
tomwalters@116 142 #ifdef _WINDOWS
tomwalters@237 143 if (filename[strlen(filename)-1]=='\\') {
tomwalters@237 144 filename[strlen(filename)-1]='\0';
tomwalters@116 145 }
tomwalters@116 146 #else
tomwalters@237 147 if (filename[strlen(filename)-1]=='/') {
tomwalters@237 148 filename[strlen(filename)-1]='\0';
tomwalters@116 149 }
tomwalters@116 150 #endif
tomwalters@116 151 // Enumerate files it m_sDir is a directory.
tomwalters@237 152 if (stat(filename, &fileinfo) == 0 && (fileinfo.st_mode & S_IFDIR)) {
tomwalters@116 153 // We have a directory: enumerate with index
tomwalters@237 154 snprintf(filename, sizeof(filename) / sizeof(filename[0]),
tomwalters@237 155 "%s%06d.%s",
tomwalters@237 156 directory_.c_str(),
tomwalters@116 157 index,
tomwalters@116 158 strPlottype);
tomwalters@116 159 // If type is 'auto', fallback to 'png'
tomwalters@116 160 if (strcmp(strPlottype, "auto")==0)
tomwalters@116 161 strPlottype = "png";
tomwalters@116 162 } else {
tomwalters@116 163 // We have a (probably non-existant) file. Auto-detect type by extension if requested
tomwalters@237 164 strncpy(filename,
tomwalters@237 165 directory_.c_str(),
tomwalters@237 166 sizeof(filename)/sizeof(filename[0]));
tomwalters@237 167 char *pDot = strrchr(filename, '.');
tomwalters@116 168 if (!pDot) {
tom@230 169 LOG_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"),
tomwalters@237 170 filename);
tomwalters@116 171 return false;
tomwalters@116 172 }
tomwalters@116 173 strPlottype = &pDot[1];
tomwalters@116 174 }
tomwalters@237 175 image_filename_ = filename;
tomwalters@116 176 m_bOutputFile= true; //! \todo Should check that it's possible to write to the file
tomwalters@116 177 }
tomwalters@237 178
tomwalters@228 179 return true;
tomwalters@116 180 }
tomwalters@116 181
tomwalters@116 182 void GraphicsOutputDeviceCairo::CloseFile() {
tomwalters@228 183 // And the output file
tomwalters@228 184 if (m_bOutputFile) {
tomwalters@237 185 cairo_surface_write_to_png(m_cSurface, image_filename_.c_str());
tomwalters@228 186 m_bOutputFile = false;
tomwalters@228 187 }
tomwalters@237 188 cairo_set_source_rgb (m_cCr, 0.0, 0.0, 0.0);
tomwalters@237 189 cairo_paint (m_cCr);
tomwalters@237 190 //cairo_destroy(m_cCr);
tomwalters@237 191 //cairo_surface_destroy(m_cSurface);
tomwalters@116 192 }
tomwalters@116 193
tomwalters@116 194 GraphicsOutputDeviceCairo::~GraphicsOutputDeviceCairo() {
tomwalters@228 195 AIM_ASSERT(!m_iPlotHandle);
tomwalters@228 196 CloseFile();
tomwalters@116 197 }
tomwalters@116 198
tomwalters@116 199 void GraphicsOutputDeviceCairo::gGrab() {
tomwalters@116 200 // Open file.
tomwalters@228 201 if (!OpenFile(m_iFileNumber)) {
tomwalters@228 202 return;
tomwalters@116 203 }
tomwalters@228 204 // Setup plotting area.
tomwalters@228 205 cairo_set_line_width (m_cCr, 0.001f);
tomwalters@228 206 gColor3f (0.0f, 0.0f, 0.0f);
tomwalters@116 207 cairo_paint (m_cCr);
tomwalters@116 208 gColor3f(1.0f, 1.0f, 0.0f);
tomwalters@116 209 }
tomwalters@116 210
tomwalters@116 211 int GraphicsOutputDeviceCairo::GetPixelFormat() {
tomwalters@116 212 return AIM_PIX_FMT_RGB24_32;
tomwalters@116 213 }
tomwalters@116 214
tomwalters@116 215 void GraphicsOutputDeviceCairo::gBeginLineStrip() {
tomwalters@228 216 m_bIsFirstVertex = true;
tomwalters@228 217 m_iVertexType = VertexTypeLine;
tomwalters@228 218 //! \todo Make line width user-settable
tomwalters@228 219 cairo_set_line_width (m_cCr, 0.001f);
tomwalters@116 220 }
tomwalters@116 221
tomwalters@116 222 void GraphicsOutputDeviceCairo::gBeginQuadStrip() {
tomwalters@228 223 m_bIsFirstVertex = true;
tomwalters@228 224 m_iVertexType = VertexTypeQuad;
tomwalters@228 225 m_iPrevVertexCount = 0;
tomwalters@116 226 cairo_set_line_width (m_cCr, 0.001f);
tomwalters@116 227 }
tomwalters@116 228
tomwalters@116 229 void GraphicsOutputDeviceCairo::gColor3f(float r, float g, float b) {
tomwalters@116 230 if (m_bInvertColors) {
tomwalters@237 231 r = 1.0 - r;
tomwalters@237 232 g = 1.0 - g;
tomwalters@237 233 b = 1.0 - b;
tomwalters@228 234 }
tomwalters@116 235 cairo_set_source_rgb (m_cCr, r, g, b);
tomwalters@116 236 }
tomwalters@116 237
tomwalters@116 238 void GraphicsOutputDeviceCairo::gVertex3f(float x, float y, float z) {
tomwalters@228 239 switch(m_iVertexType) {
tomwalters@228 240 case VertexTypeLine:
tomwalters@228 241 if (m_bIsFirstVertex) {
tomwalters@228 242 m_bIsFirstVertex = false;
tomwalters@228 243 //pl_fmove(x, y);
tomwalters@237 244 cairo_move_to(m_cCr, x, 1.0 - y);
tomwalters@228 245 } else {
tomwalters@228 246 //pl_fcont(x, y);
tomwalters@237 247 cairo_line_to(m_cCr, x, 1.0 - y);
tomwalters@228 248 }
tomwalters@228 249 break;
tomwalters@228 250 case VertexTypeQuad:
tomwalters@237 251 /* Store vertices until we have four in a row.
tomwalters@228 252 * The order of vertices when processing quads is:
tomwalters@228 253 * 1-----3-----5
tomwalters@228 254 * | | |
tomwalters@228 255 * 0-----2-----4
tomwalters@228 256 */
tomwalters@228 257 if (m_iPrevVertexCount >= 3) {
tomwalters@228 258 // Plot this quad
tomwalters@237 259 //cairo_set_source_rgb(m_cCr, 0.2, 1 - m_aPrevY[0], m_aPrevX[0]);
tomwalters@237 260 cairo_rectangle (m_cCr, m_aPrevX[2],
tomwalters@237 261 1 - m_aPrevY[2], m_aPrevX[2] - m_aPrevX[0],
tomwalters@237 262 y - m_aPrevY[2]);
tomwalters@237 263 cairo_fill (m_cCr);
tomwalters@256 264
tomwalters@237 265 /*cairo_move_to(m_cCr, , );
tomwalters@237 266 cairo_line_to(m_cCr, , 1 - m_aPrevY[1]);
tomwalters@228 267 cairo_line_to(m_cCr, x, y);
tomwalters@237 268 cairo_line_to(m_cCr, m_aPrevX[2], 1 - m_aPrevY[2]);*/
tomwalters@145 269
tomwalters@228 270 // Last vertices of this quad are the first of the next
tomwalters@228 271 m_aPrevX[0] = m_aPrevX[2];
tomwalters@228 272 m_aPrevY[0] = m_aPrevY[2];
tomwalters@228 273 m_aPrevX[1] = x;
tomwalters@228 274 m_aPrevY[1] = y;
tomwalters@228 275 m_iPrevVertexCount = 2;
tomwalters@228 276 } else {
tomwalters@228 277 // Not at the fourth, keep storing
tomwalters@228 278 m_aPrevX[m_iPrevVertexCount] = x;
tomwalters@228 279 m_aPrevY[m_iPrevVertexCount] = y;
tomwalters@228 280 m_iPrevVertexCount++;
tomwalters@228 281 }
tomwalters@228 282 break;
tomwalters@228 283 default:
tomwalters@228 284 // Should not happen
tomwalters@228 285 AIM_ASSERT(0);
tomwalters@228 286 }
tomwalters@116 287 }
tomwalters@116 288
tomwalters@116 289 void GraphicsOutputDeviceCairo::gEnd() {
tomwalters@228 290 if(m_iVertexType==VertexTypeLine)
tomwalters@116 291 cairo_stroke (m_cCr);
tomwalters@116 292 else
tomwalters@116 293 cairo_fill (m_cCr);
tomwalters@228 294 m_iVertexType = VertexTypeNone;
tomwalters@116 295 }
tomwalters@116 296
tomwalters@116 297 void GraphicsOutputDeviceCairo::gText3f(float x,
tomwalters@116 298 float y,
tomwalters@116 299 float z,
tomwalters@116 300 const char *sStr,
tomwalters@116 301 bool bRotated) {
tomwalters@232 302 //cairo_text_extents_t te;
tomwalters@228 303 if (bRotated) {
tomwalters@228 304 cairo_rotate(m_cCr, M_PI/2);
tomwalters@237 305 //cairo_move_to(m_cCr, x ,1-y);
tomwalters@228 306 cairo_show_text(m_cCr, sStr);
tomwalters@228 307 //cairo_identity_matrix(m_cCr);
tomwalters@228 308 cairo_rotate(m_cCr, -M_PI/2);
tomwalters@228 309 } else {
tomwalters@228 310 cairo_move_to(m_cCr, x ,1-y);
tomwalters@228 311 cairo_show_text(m_cCr, sStr);
tomwalters@228 312 }
tomwalters@116 313 }
tomwalters@116 314
tomwalters@116 315 void GraphicsOutputDeviceCairo::gRelease() {
tomwalters@228 316 AIM_ASSERT(m_iPlotHandle>0);
tomwalters@228 317 CloseFile();
tomwalters@228 318 // Finished this one, up to the next!
tomwalters@228 319 m_iFileNumber++;
tomwalters@116 320 }
tom@229 321 } // namespace aimc