annotate src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc @ 121:3cdaa81c3aca

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