/*
    Rosegarden
    A MIDI and audio sequencer and musical notation editor.

    This program is Copyright 2000-2008
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <richard.bown@ferventsoftware.com>

    The moral rights of Guillaume Laurent, Chris Cannam, and Richard
    Bown to claim authorship of this work have been asserted.

    Other copyrights also apply to some parts of this work.  Please
    see the AUTHORS file and individual file headers for details.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef _RG_NOTEPIXMAPFACTORY_H_
#define _RG_NOTEPIXMAPFACTORY_H_

#include "base/NotationTypes.h"
#include <map>
#include "NoteCharacter.h"
#include <string>
#include <tqfont.h>
#include <tqfontmetrics.h>
#include <tqpixmap.h>
#include <tqpoint.h>
#include "base/Event.h"
#include "gui/editors/notation/NoteCharacterNames.h"


class TQPainter;
class TQCanvasPixmap;
class TQBitmap;


namespace Rosegarden
{

namespace Guitar { class Fingering; }

class TimeSignature;
class Text;
class NoteStyle;
class NotePixmapParameters;
class NoteFont;
class NotePixmapPainter;
class NotePixmapCache;
class Clef;
class TrackHeader;

/**
 * Generates TQCanvasPixmaps for various notation items.
 */

class NotePixmapFactory 
{
public:
    NotePixmapFactory(std::string fontName = "", int size = -1);
    NotePixmapFactory(const NotePixmapFactory &);
    NotePixmapFactory &operator=(const NotePixmapFactory &);
    ~NotePixmapFactory();

    std::string getFontName() const;
    int getSize() const;

    void setSelected(bool selected) { m_selected = selected; }
    bool isSelected() const { return m_selected; }

    void setShaded(bool shaded) { m_shaded = shaded; }
    bool isShaded() const { return m_shaded; }

    void setNoteStyle(NoteStyle *style) { m_style = style; }
    const NoteStyle *getNoteStyle() const { return m_style; } 

    // Display methods -- create canvas pixmaps:

    TQCanvasPixmap* makeNotePixmap(const NotePixmapParameters &parameters);
    TQCanvasPixmap* makeRestPixmap(const NotePixmapParameters &parameters);
    TQCanvasPixmap* makeClefPixmap(const Clef &clef);
    TQCanvasPixmap* makeKeyPixmap(const Key &key,
                                 const Clef &clef,
                                 Key previousKey =
                                 Key::DefaultKey);
    TQCanvasPixmap* makeTimeSigPixmap(const TimeSignature& sig);
    TQCanvasPixmap* makeHairpinPixmap(int length, bool isCrescendo);
    TQCanvasPixmap* makeSlurPixmap(int length, int dy, bool above, bool phrasing);
    TQCanvasPixmap* makeOttavaPixmap(int length, int octavesUp);
    TQCanvasPixmap* makePedalDownPixmap();
    TQCanvasPixmap* makePedalUpPixmap();
    TQCanvasPixmap* makeUnknownPixmap();
    TQCanvasPixmap* makeTextPixmap(const Text &text);
    TQCanvasPixmap* makeGuitarChordPixmap(const Guitar::Fingering &fingering,
                                       int x, int y);

    TQCanvasPixmap* makeNoteHaloPixmap(const NotePixmapParameters &parameters);

    // Printing methods -- draw direct to a paint device:

    void drawNote(const NotePixmapParameters &parameters,
                  TQPainter &painter, int x, int y);
    void drawRest(const NotePixmapParameters &parameters,
                  TQPainter &painter, int x, int y);
    void drawHairpin(int length, bool isCrescendo,
                     TQPainter &painter, int x, int y);
    void drawSlur(int length, int dy, bool above, bool phrasing,
                  TQPainter &painter, int x, int y);
    void drawOttava(int length, int octavesUp,
                    TQPainter &painter, int x, int y);
    void drawText(const Text &text,
                  TQPainter &painter, int x, int y);

    // Other support methods for producing pixmaps for other contexts:

    static TQCanvasPixmap *makeToolbarPixmap(const char *name,
                                            bool menuSize = false);
    static TQCanvasPixmap *makeNoteMenuPixmap(timeT duration,
                                             timeT &errorReturn);
    static TQCanvasPixmap *makeMarkMenuPixmap(Mark);

    TQCanvasPixmap* makePitchDisplayPixmap(int pitch,
                                          const Clef &clef,
                                          bool useSharps);
    TQCanvasPixmap* makePitchDisplayPixmap(int pitch,
                                          const Clef &clef,
                                          int octave,
                                          int step);
    TQCanvasPixmap* makeClefDisplayPixmap(const Clef &clef);
    TQCanvasPixmap* makeKeyDisplayPixmap(const Key &key,
                                       const Clef &clef);

    TQCanvasPixmap* makeTrackHeaderPixmap(int width, int height,
                                            TrackHeader *header);

    // Bounding box and other geometry methods:

    int getNoteBodyWidth (Note::Type =
                          Note::Crotchet) const;

    int getNoteBodyHeight(Note::Type =
                          Note::Crotchet) const;

    int getAccidentalWidth (const Accidental &,
                            int shift = 0, bool extra = false) const;
    int getAccidentalHeight(const Accidental &) const;

    int getLineSpacing()        const;
    int getStemLength()         const;
    int getStemThickness()      const;
    int getStaffLineThickness() const;
    int getLegerLineThickness() const;
    int getDotWidth()           const;
    int getBarMargin()          const;

    int getClefWidth(const Clef &clef) const;
    int getTimeSigWidth(const TimeSignature &timesig) const;
    int getRestWidth(const Note &restType) const;
    int getKeyWidth(const Key &key,
                    Key previousKey = Key::DefaultKey) const;
    int getTextWidth(const Text &text) const;

    /**
     * Returns the width of clef and key signature drawn in a track header.
     */
    int getClefAndKeyWidth(const Key &key, const Clef &clef);

    /**
     * Returns the Number of Text Lines that can be written at top and bottom
     * of a track header.
     * The parameter is the track header height.
     * Always returns a value >= 1.
     */
    int getTrackHeaderNTL(int height);

    /**
     * Returns the width of a text string written in a track header.
     */
    int getTrackHeaderTextWidth(TQString str);

    /**
     * Returns the spacing of a text lines written in a track header.
     */
    int getTrackHeaderTextLineSpacing();

    /**
     * Returns from the beginning of "text" a string of horizontal size
     * "width" (when written with m_trackHeaderFont) and removes it
     * from "text".
     */
    TQString getOneLine(TQString &text, int width);


    /**
     * We need this function because as of TQt 3.1, TQCanvasPixmap
     * is no longer copyable by value, while TQPixmap still is.
     *
     * So all the makeXXPixmap are now returning TQCanvasPixmap*
     * instead of TQCanvasPixmap, but we need an easy way to
     * convert them to TQPixmap, since we use them that
     * way quite often (to generate toolbar button icons for instance).
     */
    static TQPixmap toTQPixmap(TQCanvasPixmap*);
    static void dumpStats(std::ostream &);


    static const char* const defaultSerifFontFamily;
    static const char* const defaultSansSerifFontFamily;
    static const char* const defaultTimeSigFontFamily;
    

protected:
    void init(std::string fontName, int size);
    void initMaybe() { if (!m_font) init("", -1); }

    void drawNoteAux(const NotePixmapParameters &parameters,
                     TQPainter *painter, int x, int y);
    void drawRestAux(const NotePixmapParameters &parameters, TQPoint &hotspot,
                     TQPainter *painter, int x, int y);
    void drawHairpinAux(int length, bool isCrescendo,
                        TQPainter *painter, int x, int y);
    void drawSlurAux(int length, int dy, bool above, bool smooth, bool tie, bool phrasing,
                     TQPoint &hotspot,
                     TQPainter *painter, int x, int y);
    void drawOttavaAux(int length, int octavesUp,
                       TQPainter *painter, int x, int y);
    void drawTextAux(const Text &text,
                     TQPainter *painter, int x, int y);

    int getStemLength(const NotePixmapParameters &) const;

    void makeRoomForAccidental(Accidental, bool cautionary, int shift, bool extra);
    void drawAccidental(Accidental, bool cautionary);

    void makeRoomForMarks(bool isStemmed, const NotePixmapParameters &params, int stemLength);
    void drawMarks(bool isStemmed, const NotePixmapParameters &params, int stemLength);

    void makeRoomForLegerLines(const NotePixmapParameters &params);
    void drawLegerLines(const NotePixmapParameters &params);

    void makeRoomForStemAndFlags(int flagCount, int stemLength,
                                 const NotePixmapParameters &params,
                                 TQPoint &startPoint, TQPoint &endPoint);
    void drawFlags(int flagCount, const NotePixmapParameters &params,
                   const TQPoint &startPoint, const TQPoint &endPoint);
    void drawStem(const NotePixmapParameters &params,
                  const TQPoint &startPoint, const TQPoint &endPoint,
                  int shortening);

    void makeRoomForBeams(const NotePixmapParameters &params);
    void drawBeams(const TQPoint &, const NotePixmapParameters &params,
                   int beamCount);

    void drawSlashes(const TQPoint &, const NotePixmapParameters &params,
                     int slashCount);

    void makeRoomForTuplingLine(const NotePixmapParameters &params);
    void drawTuplingLine(const NotePixmapParameters &params);

    void drawShallowLine(int x0, int y0, int x1, int y1, int thickness,
                         bool smooth);
    void drawTie(bool above, int length, int shift);

    void drawBracket(int length, bool left, bool curly, int x, int y);

    TQFont getTextFont(const Text &text) const;

    TQCanvasPixmap* makeAnnotationPixmap(const Text &text);
    TQCanvasPixmap* makeAnnotationPixmap(const Text &text, const bool isLilyPondDirective);

    void createPixmapAndMask(int width, int height,
                             int maskWidth = -1,
                             int maskHeight = -1);
    TQCanvasPixmap* makeCanvasPixmap(TQPoint hotspot, bool generateMask = false);

    enum ColourType {
        PlainColour,
        QuantizedColour,
        HighlightedColour,
        TriggerColour,
        OutRangeColour
    };

    /// draws selected/shaded status from m_selected/m_shaded:
    NoteCharacter getCharacter(CharName name, ColourType type, bool inverted);

    /// draws selected/shaded status from m_selected/m_shaded:
    bool getCharacter(CharName name, NoteCharacter &ch, ColourType type, bool inverted);

    void drawNoteHalo(int x, int y, int w, int h);

    //--------------- Data members ---------------------------------

    NoteFont *m_font;
    NoteStyle *m_style;
    bool m_selected;
    bool m_shaded;

    int m_noteBodyWidth, m_noteBodyHeight;
    int m_left, m_right, m_above, m_below;
    int m_borderX, m_borderY;

    TQFont m_tupletCountFont;
    TQFontMetrics m_tupletCountFontMetrics;

    TQFont m_textMarkFont;
    TQFontMetrics m_textMarkFontMetrics;

    TQFont m_fingeringFont;
    TQFontMetrics m_fingeringFontMetrics;

    TQFont m_timeSigFont;
    TQFontMetrics m_timeSigFontMetrics;

    TQFont m_bigTimeSigFont;
    TQFontMetrics m_bigTimeSigFontMetrics;

    TQFont m_ottavaFont;
    TQFontMetrics m_ottavaFontMetrics;

    TQFont m_clefOttavaFont;
    TQFontMetrics m_clefOttavaFontMetrics;

    TQFont m_trackHeaderFont;
    TQFontMetrics m_trackHeaderFontMetrics;

    TQFont m_trackHeaderBoldFont;
    TQFontMetrics m_trackHeaderBoldFontMetrics;

    TQPixmap *m_generatedPixmap;
    TQBitmap *m_generatedMask;

    int m_generatedWidth;
    int m_generatedHeight;
    bool m_inPrinterMethod;
    
    NotePixmapPainter *m_p;

    mutable NotePixmapCache *m_dottedRestCache;

    typedef std::map<const char *, TQFont> TextFontCache;
    mutable TextFontCache m_textFontCache;

    static TQPoint m_pointZero;
};



}

#endif
