Mercurial > hg > aimc
diff trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc @ 397:7a573750b186
- First add of a lot of graphics code from the old version. Not working yet, not even compiling yet.
author | tomwalters |
---|---|
date | Fri, 15 Oct 2010 05:40:53 +0000 |
parents | |
children | 3ee03a6b95a0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceCairo.cc Fri Oct 15 05:40:53 2010 +0000 @@ -0,0 +1,283 @@ +// Copyright 2007, Thomas Walters +// +// AIM-C: A C++ implementation of the Auditory Image Model +// http://www.acousticscale.org/AIMC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * \file + * \brief Output device for output to a graphics file using cairo (LGPL) + * + * \author Tom Walters <tom@acousticscale.org> and Willem van Engen <cnbh@willem.engen.nl> + * \date created 2007/09/17 + * \version \$Header: $ + */ + +#include "Support/Common.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "Support/util.h" +#include "Output/GraphicsOutputDeviceCairo.h" + +GraphicsOutputDeviceCairo::GraphicsOutputDeviceCairo(Parameters *pParam) + : GraphicsOutputDevice(pParam) { + m_bOutputFile = false; + m_iFileNumber = 0; + m_iVertexType = VertexTypeNone; + m_bUseMemoryBuffer=false; +} + +bool GraphicsOutputDeviceCairo::Initialize(const char *sDir) { + Init(); + + //! \todo Output to file if sDir is a file, to directory with + //! multiple images if it's a directory. + strncpy(m_sDir, sDir, sizeof(m_sDir)/sizeof(m_sDir[0])); + + /* Try to open an image to see if everything is allright. We want to avoid + * errors in the main Process()ing loop. */ + if ( !OpenFile(0) ) { + //! \todo Better error message that is more specific about the cause. + AIM_ERROR(_T("Could not open output directory '%s' using graphics format '%s'."), + m_sDir, m_pParam->GetString("output.img.format") ); + return false; + } + CloseFile(); + + return true; +} + +bool GraphicsOutputDeviceCairo::Initialize() { + Init(); + m_bUseMemoryBuffer = true; + return(true); +} + +void GraphicsOutputDeviceCairo::Init() { + AIM_ASSERT(m_pParam); + /* + * Set parameters + */ + m_pParam->GetString("output.img.color.background"); + + m_bInvertColors = m_pParam->GetBool("output.img.color.invert"); + + // Output size! + m_iWidth = m_pParam->GetUInt("output.img.width"); + m_iHeight = m_pParam->GetUInt("output.img.height"); +} + +unsigned char* GraphicsOutputDeviceCairo::GetBuffer() { + if(m_bUseMemoryBuffer) + return (cairo_image_surface_get_data (m_cSurface)); + else + return NULL; +} + +bool GraphicsOutputDeviceCairo::OpenFile(unsigned int index) { + const char *strPlottype = m_pParam->GetString("output.img.format"); + if (!m_bUseMemoryBuffer) { + struct stat fileinfo; + // Get filename without trailing slash + strncpy(m_sFilename, m_sDir, sizeof(m_sFilename)/sizeof(m_sFilename[0])); +#ifdef _WINDOWS + if (m_sFilename[strlen(m_sFilename)-1]=='\\') { + m_sFilename[strlen(m_sFilename)-1]='\0'; + } +#else + if (m_sFilename[strlen(m_sFilename)-1]=='/') { + m_sFilename[strlen(m_sFilename)-1]='\0'; + } +#endif + // Enumerate files it m_sDir is a directory. + if (stat(m_sFilename, &fileinfo) == 0 && (fileinfo.st_mode & S_IFDIR)) { + // We have a directory: enumerate with index + snprintf(m_sFilename, sizeof(m_sFilename)/sizeof(m_sFilename[0]),"%s%06d.%s", + m_sDir, + index, + strPlottype); + // If type is 'auto', fallback to 'png' + if (strcmp(strPlottype, "auto")==0) + strPlottype = "png"; + } else { + // We have a (probably non-existant) file. Auto-detect type by extension if requested + strncpy(m_sFilename, m_sDir, sizeof(m_sFilename)/sizeof(m_sFilename[0])); + char *pDot = strrchr(m_sFilename, '.'); + if (!pDot) { + AIM_ERROR(_T("Please supply extension on filename when using 'auto' format: '%s'"), + m_sFilename); + return false; + } + strPlottype = &pDot[1]; + } + m_bOutputFile= true; //! \todo Should check that it's possible to write to the file + } + // Cairo's RGB24 format has 32-bit pixels with the upper 8 bits unused. + // This is not the same as the plotutils PNG format. This information is transferred by the + // function GetPixelFormat. The pixel format is dealt with by the reciever. + m_cSurface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + m_iWidth, + m_iHeight); + m_cCr = cairo_create (m_cSurface); + cairo_scale(m_cCr, (float)m_iWidth, (float)m_iHeight); + // Now setup things for this plotter. + cairo_select_font_face(m_cCr, + m_pParam->GetString("output.img.fontname"), + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (m_cCr, 0.015); + return true; +} + +void GraphicsOutputDeviceCairo::CloseFile() { + // Plotting library + if (m_iPlotHandle>0) { + cairo_destroy(m_cCr); + m_iPlotHandle = 0; + } + // And the output file + if (m_bOutputFile) { + cairo_surface_write_to_png(m_cSurface, m_sFilename); + m_bOutputFile = false; + } + cairo_surface_destroy(m_cSurface); +} + +GraphicsOutputDeviceCairo::~GraphicsOutputDeviceCairo() { + AIM_ASSERT(!m_iPlotHandle); + CloseFile(); +} + +void GraphicsOutputDeviceCairo::gGrab() { + // Open file. + if (!OpenFile(m_iFileNumber)) { + return; + } + // Setup plotting area. + cairo_set_line_width (m_cCr, 0.001f); + gColor3f (0.0f, 0.0f, 0.0f); + cairo_paint (m_cCr); + gColor3f(1.0f, 1.0f, 0.0f); +} + +int GraphicsOutputDeviceCairo::GetPixelFormat() { + return AIM_PIX_FMT_RGB24_32; +} + +void GraphicsOutputDeviceCairo::gBeginLineStrip() { + m_bIsFirstVertex = true; + m_iVertexType = VertexTypeLine; + //! \todo Make line width user-settable + cairo_set_line_width (m_cCr, 0.001f); +} + +void GraphicsOutputDeviceCairo::gBeginQuadStrip() { + m_bIsFirstVertex = true; + m_iVertexType = VertexTypeQuad; + m_iPrevVertexCount = 0; + cairo_set_line_width (m_cCr, 0.001f); +} + +void GraphicsOutputDeviceCairo::gColor3f(float r, float g, float b) { + if (m_bInvertColors) { + r = 1-r; + g = 1-g; + b = 1-b; + } + cairo_set_source_rgb (m_cCr, r, g, b); +} + +void GraphicsOutputDeviceCairo::gVertex3f(float x, float y, float z) { + switch(m_iVertexType) { + case VertexTypeLine: + if (m_bIsFirstVertex) { + m_bIsFirstVertex = false; + //pl_fmove(x, y); + cairo_move_to(m_cCr, x, 1-y); + } else { + //pl_fcont(x, y); + cairo_line_to(m_cCr, x, 1-y); + } + break; + case VertexTypeQuad: + /* Store vertices until we got four in a row. + * The order of vertices when processing quads is: + * 1-----3-----5 + * | | | + * 0-----2-----4 + */ + if (m_iPrevVertexCount >= 3) { + // Plot this quad + cairo_move_to(m_cCr, m_aPrevX[0], 1-m_aPrevY[0]); + cairo_line_to(m_cCr, m_aPrevX[1], 1-m_aPrevY[1]); + cairo_line_to(m_cCr, x, y); + cairo_line_to(m_cCr, m_aPrevX[2], 1-m_aPrevY[2]); + cairo_close_path (m_cCr); + + // Last vertices of this quad are the first of the next + m_aPrevX[0] = m_aPrevX[2]; + m_aPrevY[0] = m_aPrevY[2]; + m_aPrevX[1] = x; + m_aPrevY[1] = y; + m_iPrevVertexCount = 2; + } else { + // Not at the fourth, keep storing + m_aPrevX[m_iPrevVertexCount] = x; + m_aPrevY[m_iPrevVertexCount] = y; + m_iPrevVertexCount++; + } + break; + default: + // Should not happen + AIM_ASSERT(0); + } +} + +void GraphicsOutputDeviceCairo::gEnd() { + if(m_iVertexType==VertexTypeLine) + cairo_stroke (m_cCr); + else + cairo_fill (m_cCr); + m_iVertexType = VertexTypeNone; +} + +void GraphicsOutputDeviceCairo::gText3f(float x, + float y, + float z, + const char *sStr, + bool bRotated) { + cairo_text_extents_t te; + if (bRotated) { + cairo_rotate(m_cCr, M_PI/2); + cairo_move_to(m_cCr, x ,1-y); + cairo_show_text(m_cCr, sStr); + //cairo_identity_matrix(m_cCr); + cairo_rotate(m_cCr, -M_PI/2); + } else { + cairo_move_to(m_cCr, x ,1-y); + cairo_show_text(m_cCr, sStr); + } +} + +void GraphicsOutputDeviceCairo::gRelease() { + AIM_ASSERT(m_iPlotHandle>0); + CloseFile(); + // Finished this one, up to the next! + m_iFileNumber++; +}