1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rosegarden
5     A MIDI and audio sequencer and musical notation editor.
6     Copyright 2000-2021 the Rosegarden development team.
7 
8     Other copyrights also apply to some parts of this work.  Please
9     see the AUTHORS file and individual file headers for details.
10 
11     This program is free software; you can redistribute it and/or
12     modify it under the terms of the GNU General Public License as
13     published by the Free Software Foundation; either version 2 of the
14     License, or (at your option) any later version.  See the file
15     COPYING included with this distribution for more information.
16 */
17 
18 #ifndef RG_NOTEPIXMAPFACTORY_H
19 #define RG_NOTEPIXMAPFACTORY_H
20 
21 #include <QGraphicsPixmapItem>
22 
23 #include "base/NotationTypes.h"
24 #include "NoteCharacter.h"
25 #include "NoteItem.h"
26 #include "base/Event.h"
27 #include "gui/editors/notation/NoteCharacterNames.h"
28 #include <map>
29 #include <string>
30 
31 #include <QFont>
32 #include <QFontMetrics>
33 #include <QPixmap>
34 #include <QPoint>
35 #include <QCoreApplication> // for Q_DECLARE_TR_FUNCTIONS
36 #include <QSharedPointer>
37 
38 class QPainter;
39 class QBitmap;
40 class QString;
41 
42 
43 namespace Rosegarden
44 {
45 
46 namespace Guitar { class Fingering; }
47 
48 class TimeSignature;
49 class Text;
50 class NoteStyle;
51 class NotePixmapParameters;
52 class NoteFont;
53 class NotePixmapPainter;
54 class Clef;
55 class StaffHeader;
56 
57 /**
58  * Generates pixmaps and graphics items for various notation items.
59  * This class is not re-entrant.
60  */
61 class NotePixmapFactory
62 {
63     Q_DECLARE_TR_FUNCTIONS(Rosegarden::NotePixmapFactory)
64 
65 public:
66     static const int NO_GRACE_SIZE = -1;
67 
68     NotePixmapFactory(QString fontName = "", int size = -1, int graceSize = NO_GRACE_SIZE);
69     NotePixmapFactory(const NotePixmapFactory &);
70     NotePixmapFactory &operator=(const NotePixmapFactory &);
71     ~NotePixmapFactory();
72 
73     QString getFontName() const;
74     int getSize() const;
75 
76    /**
77     \enum ColourType
78 
79     This enum describes the different colours that may be used to draw
80     notation-related glyphs.  This aspect of drawing is handled through this
81     enum, rather than by specifying a colour explicitly.  If you have some
82     occasion to add more colours for some new purpose, do so through this enum
83     (realising that you have to hook it all up somewhere to make use of the new
84     values defined!)
85 
86     \sa GUIPalette, TrackParameterBox, PresetHandlerDialog
87     */
88     enum ColourType {
89         PlainColour,        /**< The default basic Qt::black (hard coded) */
90         QuantizedColour,    /**< Defined in GUIPalette; used when quantized notes are indicated */
91         HighlightedColour,  /**< Defined in GUIPalette; used when notes (&c.) are shown in the selected state */
92         TriggerColour,      /**< Defined in GUIPalette; used when trigger notes are indicated */
93         TriggerSkipColour,   /**< Defined in GUIPalette; used when masked-out trigger notes within ties are indicated */
94         OutRangeColour,     /**< Defined in GUIPalette; used when out-of-range notes are indicated */
95         PlainColourLight,   /**< The default basic Qt::white (hard coded) used when drawing on a black background */
96         ConflictColour,      /**< Qt::red (hard coded) used by track headers to indicate, eg. a clef conflict */
97         MemberOfParallelColour /**< for members of parallels */
98     };
99 
100     /** Used to notify the drawing code that the character is selected, and
101      * should therefore be drawn with a blue foreground
102      */
setSelected(bool selected)103     void setSelected(bool selected) { m_selected = selected; }
104 
105     /** Returns true if the character is in the selected state
106      */
isSelected()107     bool isSelected() const { return m_selected; }
108 
getGraceSize()109     int getGraceSize() const { return m_graceSize; }
110 
111     /** Used to notify the drawing code that the character is shaded, and should
112      * therefore be drawn with a gray foreground.  This is used for "invisible"
113      * items
114      */
setShaded(bool shaded)115     void setShaded(bool shaded) { m_shaded = shaded; }
116 
117     /** Returns true if the character is in the shaded (ie. "invisible") state
118      */
isShaded()119     bool isShaded() const { return m_shaded; }
120 
setNoteStyle(QSharedPointer<NoteStyle> style)121     void setNoteStyle(QSharedPointer<NoteStyle> style) { m_style = style; }
getNoteStyle()122     const QSharedPointer<NoteStyle> getNoteStyle() const { return m_style; }
123 
124     // Display methods -- create graphics items:
125 
126     QGraphicsItem *makeNote(const NotePixmapParameters &parameters);
127     QGraphicsItem *makeRest(const NotePixmapParameters &parameters);
128 
129     QGraphicsPixmapItem *makeNotePixmapItem(const NotePixmapParameters &parameters);
130 
131     void getNoteDimensions(const NotePixmapParameters &parameters,
132                            NoteItemDimensions &dimensions);
133 
134     void drawNoteForItem(const NotePixmapParameters &parameters,
135                          const NoteItemDimensions &dimensions,
136                          NoteItem::DrawMode mode,
137                          QPainter *painter);
138 
139     /** Make a clef pixmap from Clef &clef.  The optional colourType parameter
140      * is used to pass a ColourType through makeClef() into drawCharacter() for
141      * certain special situations requiring external control of the glyph colour
142      * (eg. track headers)
143      */
144     QGraphicsPixmapItem *makeClef(const Clef &clef, const ColourType colourType = PlainColour);
145 
146     /** Make a symbol pixmap from Symbol &symbol.
147      *
148      * \sa makeClef
149      */
150     QGraphicsPixmapItem *makeSymbol(const Symbol &symbol, const ColourType colourType = PlainColour);
151 
152     QGraphicsPixmapItem *makeKey(const Key &key,
153                                  const Clef &clef,
154                                  Key previousKey =
155                                  Key::DefaultKey,
156                                  const ColourType colourType = PlainColour);
157     QGraphicsPixmapItem *makeTimeSig(const TimeSignature& sig);
158     QGraphicsPixmapItem *makeHairpin(int length, bool isCrescendo);
159     QGraphicsPixmapItem *makeSlur(int length, int dy, bool above, bool phrasing);
160     QGraphicsPixmapItem *makeOttava(int length, int octavesUp);
161     QGraphicsPixmapItem *makePedalDown();
162     QGraphicsPixmapItem *makePedalUp();
163     QGraphicsPixmapItem *makeUnknown();
164     QGraphicsPixmapItem *makeText(const Text &text);
165     QGraphicsPixmapItem *makeGuitarChord(const Guitar::Fingering &fingering,
166                                        int x, int y);
167     QGraphicsPixmapItem *makeTrillLine(int length);
168 
169     QGraphicsPixmapItem *makeNoteHalo(const NotePixmapParameters &parameters);
170 
171     // Printing methods -- draw direct to a paint device:
172 
173     void drawNote(const NotePixmapParameters &parameters,
174                   QPainter &painter, int x, int y);
175     void drawRest(const NotePixmapParameters &parameters,
176                   QPainter &painter, int x, int y);
177     void drawHairpin(int length, bool isCrescendo,
178                      QPainter &painter, int x, int y);
179     void drawSlur(int length, int dy, bool above, bool phrasing,
180                   QPainter &painter, int x, int y);
181     void drawOttava(int length, int octavesUp,
182                     QPainter &painter, int x, int y);
183     void drawText(const Text &text,
184                   QPainter &painter, int x, int y);
185 
186     // Other support methods for producing pixmaps for other contexts:
187 
188     static QPixmap makeToolbarPixmap(QString name, bool menuSize = false);
189     static QPixmap makeNoteMenuPixmap(timeT duration, timeT &errorReturn);
190     static QPixmap makeMarkMenuPixmap(Mark);
191 
192     QPixmap makePitchDisplayPixmap(int pitch,
193                                    const Clef &clef,
194                                    bool useSharps,
195                                    const ColourType = PlainColour);
196     QPixmap makePitchDisplayPixmap(int pitch,
197                                    const Clef &clef,
198                                    int octave,
199                                    int step,
200                                    const ColourType = PlainColour);
201     QPixmap makeClefDisplayPixmap(const Clef &clef, const ColourType colourType = PlainColour);
202     QPixmap makeKeyDisplayPixmap(const Key &key,
203                                  const Clef &clef,
204                                  const ColourType colourType = PlainColour);
205     QPixmap makeTextPixmap(const Text &text);
206 
207     // Bounding box and other geometry methods:
208 
209     int getNoteBodyWidth (Note::Type =
210                           Note::Crotchet) const;
211 
212     int getNoteBodyHeight(Note::Type =
213                           Note::Crotchet) const;
214 
215     int getAccidentalWidth (const Accidental &,
216                             int shift = 0, bool extra = false) const;
217     int getAccidentalHeight(const Accidental &) const;
218 
219     int getLineSpacing()        const;
220     int getStemLength()         const;
221     int getStemThickness()      const;
222     int getStaffLineThickness() const;
223     int getLegerLineThickness() const;
224     int getDotWidth()           const;
225     int getBarMargin()          const;
226 
227     int getClefWidth(const Clef &clef) const;
228     int getTimeSigWidth(const TimeSignature &timesig) const;
229     int getRestWidth(const Note &restType) const;
230     int getKeyWidth(const Key &key,
231                     Key previousKey = Key::DefaultKey) const;
232     int getTextWidth(const Text &text) const;
233 
234     /**
235      * Returns the width of clef and key signature drawn in a track header.
236      */
237     int getClefAndKeyWidth(const Key &key, const Clef &clef);
238 
239     /**
240      * Returns the Number of Text Lines that can be written at top and bottom
241      * of a track header.
242      * The parameter is the track header height.
243      * Always returns a value >= 1.
244      */
245     int getTrackHeaderNTL(int height);
246 
247     /**
248      * Returns the width of a text string written in a track header.
249      */
250     int getTrackHeaderTextWidth(QString str);
251 
252     /**
253      * Returns the spacing of a text lines written in a track header.
254      */
255     int getTrackHeaderTextLineSpacing();
256 
257     /**
258      * Returns from the beginning of "text" a string of horizontal size
259      * "width" (when written with m_trackHeaderFont) and removes it
260      * from "text".
261      */
262     QString getOneLine(QString &text, int width);
263 
getTrackHeaderFont()264     QFont getTrackHeaderFont() { return m_trackHeaderFont; }
getTrackHeaderFontMetrics()265     QFontMetrics getTrackHeaderFontMetrics() { return m_trackHeaderFontMetrics; }
266 
getTrackHeaderBoldFont()267     QFont getTrackHeaderBoldFont() { return m_trackHeaderBoldFont; }
getTrackHeaderBoldFontMetrics()268     QFontMetrics getTrackHeaderBoldFontMetrics() {
269         return m_trackHeaderBoldFontMetrics;
270     }
271 
272     static void dumpStats(std::ostream &);
273 
274 
275     static const char* const defaultSerifFontFamily;
276     static const char* const defaultSansSerifFontFamily;
277     static const char* const defaultTimeSigFontFamily;
278 
279 protected:
280     void init(QString fontName, int size);
initMaybe()281     void initMaybe() { if (!m_font) init("", -1); }
282 
283     void calculateNoteDimensions(const NotePixmapParameters &parameters);
284     void sketchNoteTiny(const NotePixmapParameters &parameters,
285                         const NoteItemDimensions &dimensions,
286                         QPainter *painter);
287     void drawNoteAux(const NotePixmapParameters &parameters,
288                      QPainter *painter, int x, int y);
289     void drawRestAux(const NotePixmapParameters &parameters, QPoint &hotspot,
290                      QPainter *painter, int x, int y);
291     void drawHairpinAux(int length, bool isCrescendo,
292                         QPainter *painter, int x, int y);
293     void drawSlurAux(int length, int dy, bool above, bool smooth, bool tie, bool phrasing,
294                      QPoint &hotspot,
295                      QPainter *painter, int x, int y);
296     void drawOttavaAux(int length, int octavesUp,
297                        QPainter *painter, int x, int y);
298     void drawTextAux(const Text &text,
299                      QPainter *painter, int x, int y);
300     void drawTrillLineAux(int length, QPainter *painter, int x, int y);
301 
302     int getStemLength(const NotePixmapParameters &) const;
303 
304     void makeRoomForAccidental(Accidental, bool cautionary, int shift, bool extra);
305     void drawAccidental(const NotePixmapParameters &params);
306 
307     void makeRoomForMarks(bool isStemmed, const NotePixmapParameters &params, int stemLength);
308     void drawMarks(bool isStemmed, const NotePixmapParameters &params, int stemLength, bool overRestHack = false);
309 
310     void makeRoomForLegerLines(const NotePixmapParameters &params);
311     void drawLegerLines(const NotePixmapParameters &params);
312 
313     void makeRoomForStemAndFlags(int flagCount, int stemLength,
314                                  const NotePixmapParameters &params,
315                                  QPoint &startPoint, QPoint &endPoint);
316     void drawFlags(int flagCount, const NotePixmapParameters &params,
317                    const QPoint &startPoint, const QPoint &endPoint);
318     void drawStem(const NotePixmapParameters &params,
319                   const QPoint &startPoint, const QPoint &endPoint,
320                   int shortening);
321 
322     void makeRoomForBeams(const NotePixmapParameters &params);
323     void drawBeams(const QPoint &, const NotePixmapParameters &params,
324                    int beamCount);
325 
326     void drawSlashes(const QPoint &, const NotePixmapParameters &params,
327                      int slashCount);
328 
329     void makeRoomForTuplingLine(const NotePixmapParameters &params);
330     void drawTuplingLine(const NotePixmapParameters &params);
331 
332     void drawShallowLine(float x0, float y0, float x1, float y1, float thickness);
333     void drawTie(bool above, int length, int shift);
334 
335     /// Draw a parenthesis for cautionary (courtesy) accidentals.
336     void drawBracket(int length, bool left, bool curly, int x, int y);
337 
338     QFont getTextFont(const Text &text) const;
339 
340     QGraphicsPixmapItem *makeAnnotation(const Text &text);
341     QGraphicsPixmapItem *makeAnnotation(const Text &text,
342                                         const bool isLilyPondDirective);
343 
344     void createPixmap(int width, int height);
345     QGraphicsPixmapItem *makeItem(QPoint hotspot);
346     QPixmap makePixmap();
347 
348     /// draws selected/shaded status from m_selected/m_shaded:
349     NoteCharacter getCharacter(CharName name, ColourType type, bool inverted);
350 
351     /// draws selected/shaded status from m_selected/m_shaded:
352     bool getCharacter(CharName name, NoteCharacter &ch, ColourType type, bool inverted);
353 
354     /// Draw character with a specified QColor
355     //  This is a first step to a simpler use of colors
356     NoteCharacter getCharacter(CharName name, QColor color, bool inverted);
357 
358     /// Draw character with a specified QColor
359     //  This is a first step to a simpler use of colors
360     bool getCharacter(CharName name, NoteCharacter &ch, QColor color, bool inverted);
361 
362     void drawNoteHalo(int x, int y, int w, int h);
363 
364     //--------------- Data members ---------------------------------
365 
366     NoteFont *m_font;
367     NoteFont *m_graceFont;
368     QSharedPointer<NoteStyle> m_style;
369     bool m_selected;
370     bool m_shaded;
371     bool m_haveGrace;
372 
373     int m_graceSize;
374 
375     NoteItemDimensions m_nd;
376 
377     QFont m_tupletCountFont;
378     QFontMetrics m_tupletCountFontMetrics;
379 
380     QFont m_textMarkFont;
381     QFontMetrics m_textMarkFontMetrics;
382 
383     QFont m_fingeringFont;
384     QFontMetrics m_fingeringFontMetrics;
385 
386     QFont m_timeSigFont;
387     QFontMetrics m_timeSigFontMetrics;
388 
389     QFont m_bigTimeSigFont;
390     QFontMetrics m_bigTimeSigFontMetrics;
391 
392     QFont m_ottavaFont;
393     QFontMetrics m_ottavaFontMetrics;
394 
395     QFont m_clefOttavaFont;
396     QFontMetrics m_clefOttavaFontMetrics;
397 
398     QFont m_trackHeaderFont;
399     QFontMetrics m_trackHeaderFontMetrics;
400 
401     QFont m_trackHeaderBoldFont;
402     QFontMetrics m_trackHeaderBoldFontMetrics;
403 
404     QPixmap *m_generatedPixmap;
405 
406     int m_generatedWidth;
407     int m_generatedHeight;
408     bool m_inPrinterMethod;
409 
410     NotePixmapPainter *m_p;
411 
412     typedef std::map<const char *, QFont> TextFontCache;
413     mutable TextFontCache m_textFontCache;
414 };
415 
416 
417 
418 }
419 
420 #endif
421