1
//--------------------------------------------------------------------------------------
2
// LenMus Phonascus: The teacher of music
3
// Copyright (c) 2002-2007 Cecilio Salmeron
5
// This program is free software; you can redistribute it and/or modify it under the
6
// terms of the GNU General Public License as published by the Free Software Foundation;
7
// either version 2 of the License, or (at your option) any later version.
9
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
10
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
// You should have received a copy of the GNU General Public License along with this
14
// program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
15
// Fifth Floor, Boston, MA 02110-1301, USA.
17
// For any comment, suggestion or feature request, please contact the manager of
18
// the project at cecilios@users.sourceforge.net
20
//-------------------------------------------------------------------------------------
22
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
23
#pragma implementation "GraphicManager.h"
26
// For compilers that support precompilation, includes "wx.h".
27
#include "wx/wxprec.h"
35
#include "GraphicManager.h"
36
#include "Formatter4.h"
37
#include "AggDrawer.h"
38
#include "../score/ObjOptions.h"
41
#include "../globals/Colors.h"
42
extern lmColors* g_pColors;
44
// Definition of the BitmapList class
45
#include <wx/listimpl.cpp>
46
WX_DEFINE_LIST(BitmapList);
48
// access to global some global flags
49
extern bool g_fUseAntiAliasing; // in TheApp.cpp
51
//-----------------------------------------------------------------------------------------
53
lmGraphicManager::lmGraphicManager()
55
Create((lmScore*)NULL, (lmPaper*)NULL);
58
lmGraphicManager::lmGraphicManager(lmScore* pScore, lmPaper* pPaper)
60
Create(pScore, pPaper);
63
void lmGraphicManager::Create(lmScore* pScore, lmPaper* pPaper)
69
m_pBoxScore = (lmBoxScore*) NULL;
76
m_nHighlightedPage = 0;
77
m_pAuxBitmap = (wxBitmap*)NULL;
84
lmGraphicManager::~lmGraphicManager()
88
m_pBoxScore = (lmBoxScore*) NULL;
95
m_pAuxBitmap = (wxBitmap*)NULL;
100
int lmGraphicManager::GetNumPages()
103
return m_pBoxScore->GetNumPages();
108
void lmGraphicManager::Layout()
110
// The goal of this method is to parse the IIR representation of a score and
111
// generate the graphical representation so that it can be displayed or printed.
112
// The result is a lmBoxScore object.
116
m_pBoxScore = (lmBoxScore*) NULL;
118
lmFormatter4 oFormatter; //the formatter object
119
m_pBoxScore = oFormatter.Layout(m_pScore, m_pPaper);
120
wxASSERT(m_pBoxScore);
125
void lmGraphicManager::Render()
127
if (!m_pBoxScore) return;
128
m_pBoxScore->Render(m_pPaper);
132
wxBitmap* lmGraphicManager::Render(bool fUseBitmaps, int nPage)
137
//Render page directly on the DC
138
if (m_pBoxScore) m_pBoxScore->RenderPage(nPage, m_pPaper);
139
return (wxBitmap*)NULL;
142
//Return the offscreen bitmap for the requested page
143
wxBitmap* pBitmap = GetPageBitmap(nPage);
145
if (!g_fUseAntiAliasing) {
146
// standard DC renderization. Aliased.
147
pBitmap = NewBitmap(nPage);
148
wxMemoryDC memDC; // Allocate a DC in memory for the offscreen bitmap
149
memDC.SelectObject(*pBitmap);
150
m_pPaper->SetDrawer(new lmDirectDrawer(&memDC));
152
memDC.SetMapMode(lmDC_MODE);
153
memDC.SetUserScale( m_rScale, m_rScale );
154
m_pBoxScore->RenderPage(nPage, m_pPaper);
155
memDC.SelectObject(wxNullBitmap);
158
// anti-aliased renderization
160
pBitmap = new wxBitmap(1, 1); //allocate something to paint on it
161
memDC.SelectObject(*pBitmap);
162
memDC.SetMapMode(lmDC_MODE);
163
memDC.SetUserScale( m_rScale, m_rScale );
164
lmAggDrawer* pDrawer = new lmAggDrawer(&memDC, m_xPageSize, m_yPageSize);
165
m_pPaper->SetDrawer(pDrawer);
166
wxASSERT(m_pBoxScore); //Layout phase omitted?
167
m_pBoxScore->RenderPage(nPage, m_pPaper);
169
memDC.SelectObject(wxNullBitmap);
172
//Make room for the new bitmap
175
//Add bitmap to the offscreen collection
176
pBitmap = new wxBitmap(pDrawer->GetImageBuffer());
177
AddBitmap(nPage, pBitmap);
184
void lmGraphicManager::PrepareForHighlight()
186
// The score is going to be highlighted while played back. This method
187
// saves de AGGDrawer bitmap buffers, to achive fast un-highlight by just
188
// restoring the original bitmap.
189
//wxLogMessage(_T("[lmGraphicManager::PrepareForHighlight]"));
191
//If this method is invoked, a score must be currently displayed. This implies
192
//that Layout() has benn invoked and, therefore, a BoxScore object exists.
193
wxASSERT(m_pBoxScore); //Layout phase omitted?
195
//If anti-aliased is not used there is nothing to do in this method
196
if (!g_fUseAntiAliasing) return;
198
//If anti-aliased is used, bitmaps must exist, at least for currently displayed page.
199
wxASSERT(m_cBitmaps.GetCount() > 0);
201
//As we do not know which bitmap to save ("Play" normally starts at page 1 but
202
//not always: i.e. when starting at a certain measure number) this method
203
//just deletes all auxiliary bitmap data.
204
m_nHighlightedPage = 0;
207
m_pAuxBitmap = (wxBitmap*)NULL;
210
//Finally, signal that all upcoming drawing is for highlight
215
void lmGraphicManager::Prepare(lmScore* pScore, lmLUnits paperWidth, lmLUnits paperHeight,
216
double rScale, lmPaper* pPaper, int nOptions)
218
//This method informs GraphicManager about the common parameters (the score,
219
//the paper, the scale, etc..) for a series of to subsequent Render()
221
//The GraphicManager must verify if all stored values are stil valid and, if not,
222
//do whatever is necessary, i.e. delete invalid offscreen bitmaps.
223
//Also, it must prepare anything that could be necessary, i.e. force a re-layout
228
//Is it necessary to force a re-layout?
229
// Yes in following cases:
230
// - the first time a score is going to be rendered
231
// - if paper size has changed and so requested (option lmRELAYOUT_ON_PAPER_SIZE_CHANGE)
232
// - if explicitly requested (option lmFORCE_RELAYOUT)
233
bool fLayoutScore = !m_pScore || m_fReLayout
234
|| m_nLastScoreID != pScore->GetID()
235
|| (nOptions & lmFORCE_RELAYOUT)
236
|| ( (nOptions & lmRELAYOUT_ON_PAPER_SIZE_CHANGE) &&
237
(m_xPageSize != paperWidth || m_yPageSize != paperHeight) );
239
//Is it necessary to delete stored offscreen bitmaps?
240
//Yes in following cases:
241
// - When the scale (zooming factor) has changed
242
// - When a re-layout takes place
243
bool fDeleteBitmaps = (m_rScale != rScale) || fLayoutScore;
245
//store received values
248
m_xPageSize = paperWidth;
249
m_yPageSize = paperHeight;
251
m_nLastScoreID = m_pScore->GetID();
253
//re-layout the score if necesary
254
if (fLayoutScore) Layout();
256
//delete existing offscreen bitmaps if necessary
257
if (fDeleteBitmaps) DeleteBitmaps();
259
//wxLogMessage(_T("[lmGraphicManager::Prepare] fLayoutScore=%s, fDeleteBitmaps=%s, Hay BoxScore=%s"),
260
// (fLayoutScore ? _T("Yes") : _T("No")),
261
// (fDeleteBitmaps ? _T("Yes") : _T("No")),
262
// (m_pBoxScore ? _T("Yes") : _T("No")) );
266
void lmGraphicManager::DeleteBitmaps()
268
wxBitmapListNode* pNode = m_cBitmaps.GetFirst();
270
wxBitmap* pBitmap = pNode->GetData();
273
pNode = m_cBitmaps.GetFirst();
275
m_aBitmapPage.Clear();
279
wxBitmap* lmGraphicManager::GetPageBitmap(int nPage)
282
// Get the bitmap for requested page, or NULL if no bitmap exits for that page.
287
for (i=0; i < (int)m_cBitmaps.GetCount(); i++) {
288
if (m_aBitmapPage.Item(i) == nPage) {
289
wxBitmapListNode* pNode = m_cBitmaps.Item(i);
290
return (wxBitmap*)pNode->GetData();
293
return (wxBitmap*)NULL;
297
wxBitmap* lmGraphicManager::NewBitmap(int nPage)
300
// Makes room for a new bitmap, for page nPage
301
// and returns it (empty bitmap)
303
//wxLogMessage(_T("[lmGraphicManager::NewBitmap] Page = %d"), nPage);
305
//Make room for the new bitmap
308
//Allocate the new bit map
309
wxBitmap* pBitmap = new wxBitmap(m_xPageSize, m_yPageSize);
310
//wxLogMessage(_T("[lmGraphicManager::NewBitmap] Allocated bitmap (%d, %d) pixels, %d bits/pixel. Size= %.02f MB"),
311
// m_xPageSize, m_yPageSize, pBitmap->GetDepth(), (double)((m_xPageSize * m_yPageSize * pBitmap->GetDepth())/8000000.) );
312
if (!pBitmap || !pBitmap->Ok()) {
315
pBitmap = (wxBitmap *) NULL;
317
wxLogMessage(_T("[lmGraphicManager::NewBitmap] Bitmap size (%d, %d) pixels."), m_xPageSize, m_yPageSize);
318
wxMessageBox(_("Sorry, not enough memory to create a Bitmap to display the page."),
319
_T("lmGraphicManager::NewBitmap"), wxOK);
323
// add the new bitmap to the list and store its size
324
AddBitmap(nPage, pBitmap);
329
void lmGraphicManager::AddBitmap(int nPage, wxBitmap* pBitmap)
332
// Adds the received bitmap to the list, associating it to page nPage
334
//wxLogMessage(_T("[lmGraphicManager::AddBitmap] Page = %d"), nPage);
336
// add the new bitmap to the list and store its size
337
m_cBitmaps.Append(pBitmap);
338
m_aBitmapPage.Add(nPage);
340
m_xBitmapSize = m_xPageSize;
341
m_yBitmapSize = m_yPageSize;
345
void lmGraphicManager::BitmapsToFile(wxString& sFilename, wxString& sExt, int nImgType)
347
wxASSERT(nImgType == wxBITMAP_TYPE_BMP || nImgType == wxBITMAP_TYPE_JPEG
348
|| nImgType == wxBITMAP_TYPE_PNG || nImgType == wxBITMAP_TYPE_PCX
349
|| nImgType == wxBITMAP_TYPE_PNM);
351
wxBitmapListNode* pNode = m_cBitmaps.GetFirst();
354
wxBitmap* pBitmap = pNode->GetData();
355
wxImage oImg = pBitmap->ConvertToImage();
356
wxString sName = wxString::Format(_T("%s_%d.%s"), sFilename, m_aBitmapPage.Item(i-1), sExt);
357
oImg.SaveFile(sName, nImgType);
358
pNode = pNode->GetNext();
364
void lmGraphicManager::ExportAsImage(wxString& sFilename, wxString& sExt, int nImgType)
366
//Before invoking this method, Prepare() must be invoked
368
wxASSERT(nImgType == wxBITMAP_TYPE_BMP || nImgType == wxBITMAP_TYPE_JPEG
369
|| nImgType == wxBITMAP_TYPE_PNG || nImgType == wxBITMAP_TYPE_PCX
370
|| nImgType == wxBITMAP_TYPE_PNM);
374
for(i=1; i <= GetNumPages(); i++) {
375
wxBitmap* pBitmap = Render(lmUSE_BITMAPS, i);
376
wxImage oImg = pBitmap->ConvertToImage();
377
wxString sName = wxString::Format(_T("%s_%d.%s"), sFilename, m_aBitmapPage.Item(i-1), sExt);
378
oImg.SaveFile(sName, nImgType);