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