annotate trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc @ 402:69466da9745e

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