<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 <NAME> <<EMAIL>>"
// Copyright 2007      <NAME>  <<EMAIL>>"
//

#include "PlaceMarkPainter.h"

#include <QtCore/QAbstractItemModel>
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtCore/QPoint>
#include <QtCore/QVector>
#include <QtCore/QVectorIterator>
#include <QtGui/QIcon>
#include <QtGui/QPainter>

#include "global.h"
#include "PlaceMark.h"
#include "MarbleDirs.h"
#include "ViewParams.h"


// ================================================================
//                     class VisiblePlaceMark


class VisiblePlaceMark
{
 public:
    VisiblePlaceMark( PlaceMark *mark );
    ~VisiblePlaceMark();

    PlaceMark *placeMark() const                { return m_placeMark;  }
    void setPlaceMark( PlaceMark *_mark )       { m_placeMark = _mark; }

    const QPixmap  symbolPixmap() const { return m_placeMark->symbolPixmap();}
    const QSize    symbolSize()   const { return m_placeMark->symbolSize();  }

    const QPoint& symbolPos() const             { return m_symbolPos;   }
    void setSymbolPos( const QPoint& sympos )   { m_symbolPos = sympos; }
    void setSymbolPos( const int x, const int y ) {
	m_symbolPos = QPoint( x, y );
    }

    const QPixmap& labelPixmap() const          { return m_labelPixmap;       }
    void setLabelPixmap( QPixmap& labelPixmap ) { m_labelPixmap = labelPixmap;}

    void clearLabelPixmap() {
        if ( m_labelPixmap.isNull() == false )
            m_labelPixmap = QPixmap();
    }

    const QRect& labelRect() const              { return m_labelRect;    }
    void setLabelRect( const QRect& labelRect ) { m_labelRect = labelRect;}

 private:
    PlaceMark  *m_placeMark;	// the actual PlaceMark

    // View stuff
    QPoint      m_symbolPos;	// position of the placemark's symbol
    QPixmap     m_labelPixmap;	// the text label (most often name)
    QRect       m_labelRect;    // bounding box of label
};


VisiblePlaceMark::VisiblePlaceMark( PlaceMark *mark )
    : m_symbolPos(),
      m_labelPixmap(),
      m_labelRect()
{
    m_placeMark = mark;
}


VisiblePlaceMark::~VisiblePlaceMark()
{
}


// ================================================================
//                     class PlaceMarkPainter


static const int  maxlabels = 100;

PlaceMarkPainter::PlaceMarkPainter(QObject* parent)
    : QObject(parent),
      m_visiblePlacemarks(),
      m_visiblePlacemarksPool()
{
#ifdef Q_OS_MACX
    m_font_mountain = QFont( "Sans Serif",9, 50, false );

    m_font_regular           = QFont( "Sans Serif", 10, 50, false );
    m_font_regular_italics   = QFont( "Sans Serif", 10, 50, true );
    m_font_regular_underline = QFont( "Sans Serif", 10, 50, false );
#else
    m_font_mountain          = QFont( "Sans Serif",  7, 50, false );

    m_font_regular           = QFont( "Sans Serif",  8, 50, false );
    m_font_regular_italics   = QFont( "Sans Serif",  8, 50, true );
    m_font_regular_underline = QFont( "Sans Serif",  8, 50, false );
#endif

    m_font_regular_underline.setUnderline( true );

    m_fontheight = QFontMetrics( m_font_regular ).height();
    m_fontascent = QFontMetrics( m_font_regular ).ascent();

    m_labelareaheight = 2 * m_fontheight;

    m_labelcolor = QColor( 0, 0, 0, 255 );

    m_weightfilter
        << 9999
        << 4200
        << 3900
        << 3600

        << 3300
        << 3000
        << 2700
        << 2400

        << 2100
        << 1800
        << 1500
        << 1200

        << 900
        << 400
        << 200
        << 0;

    m_useXWorkaround = testXBug();
    qDebug() << "Use workaround: " << ( m_useXWorkaround ? "1" : "0" );
    // m_useXWorkaround = true;
}


#if 1

void PlaceMarkPainter::paintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    switch( viewParams->m_projection ) {
        case Spherical:
            sphericalPaintPlaceFolder(    painter, imgwidth, imgheight,
                                          viewParams, placecontainer,
                                          planetAxis, firstTime );
            break;
        case Equirectangular:
            rectangularPaintPlaceFolder(  painter, imgwidth, imgheight,
                                          viewParams, placecontainer,
                                          planetAxis, firstTime );
            break;
        default:
            qDebug()<<"Projection not supported";
    }

}

void PlaceMarkPainter::sphericalPaintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    //int  imgwidth  = 2 * imgrx;
    //int  imgheight = 2 * imgry;
    int  x = 0;
    int  y = 0;

    int  secnumber = imgheight / m_labelareaheight + 1;
#if 0
      if ( mark->name().contains( "London" ) ){
      qDebug() << "London" << " y: " << QString::number( y ) << " qpos.v[Q_Y]: " << QString::number( qpos.v[Q_Y] );
      invplanetAxis.display();
      }
#endif
    // planetAxis.display();

    Quaternion  invplanetAxis = planetAxis.inverse();
    Quaternion  qpos;

    painter->setPen(QColor(Qt::black));

    QPainter    textpainter;

    QFont       font;

    const double outlineWidth = 2.5;
    int          textWidth = 0;

    PlaceMark*  firstMark = *(placecontainer->begin());
    const bool  noFilter = ( firstMark->population() == 0 
                             || ( firstMark->population() != 0
                             && firstMark->role().isNull() ) ) 
                           ? true : false;

    QPixmap     textpixmap;

    QVector< QVector< PlaceMark* > >  m_rowsection;
    for ( int i = 0; i < secnumber; i++)
        m_rowsection.append( QVector<PlaceMark*>( ) );

    if ( firstTime )
        m_visiblePlacemarks.clear();

    PlaceMark  *mark = 0;
    int         labelnum = 0;
    PlaceMarkContainer::const_iterator  it;
    for ( it = placecontainer->constBegin();
          it != placecontainer->constEnd();
          it++ )
    {
        mark  = *it; // no cast

        // Skip the places that are too small.
        if ( noFilter == false ) {
            if ( m_weightfilter.at( mark->popidx() ) > viewParams->m_radius
                 && mark->selected() == 0 )
                continue;
        }
        else {
            mark->setSymbol(21);
        }

        // Skip terrain marks if we're not showing terrain.
        if ( !viewParams->m_showTerrain
             && ( mark->symbol() >= 16 && mark->symbol() <= 20 ) )
            continue;

        // Skip city marks if we're not showing cities.
        if ( !viewParams->m_showCities
             && ( mark->symbol() >= 0 && mark->symbol() < 16 ) )
            continue;

        qpos       = mark->quaternion();
        textpixmap = mark->textPixmap();
        qpos.rotateAroundAxis(invplanetAxis);

        // Skip placemarks at the other side of the earth.
        if ( qpos.v[Q_Z] < 0 ) {
            // FIXME: Should this be removed here or inserted in all
            //        the other skips like this?
            mark->clearTextPixmap();
            continue;
        }

        // Let (x, y) be the position on the screen of the placemark..
        x = (int)(imgwidth  / 2 + viewParams->m_radius * qpos.v[Q_X]);
        y = (int)(imgheight / 2 + viewParams->m_radius * qpos.v[Q_Y]);

        // Skip placemarks that are outside the screen area
        if ( x < 0 || x >= imgwidth || y < 0 || y >= imgheight ) {
            mark->clearTextPixmap();
            continue;
        }

        // ----------------------------------------------------------------
        // End of checks. Here the actual painting starts.

        // Choose Section
        const QVector<PlaceMark*>  currentsec = m_rowsection.at( y / m_labelareaheight );

        // Specify font properties
        if ( textpixmap.isNull() ) {
            labelFontData( mark, outlineWidth,
                           font, textWidth );
        }
        else {
            textWidth = ( mark->textRect() ).width();
        }

        // Find out whether the area around the placemark is covered already.
        if ( !roomForLabel( currentsec, mark,
                            textWidth, x, y ) )
        {
            // Don't clear the text pixmap here, for the label should
            // really be painted, but there is just too many other
            // labels around it so there is no room.
            continue;
        }

        // Paint the label
        if ( textpixmap.isNull() ) {
            // Draw the text on the label.

            // Due to some XOrg bug this requires a workaround via
            // QImage in some cases.

            if ( !m_useXWorkaround ) {
                textpixmap = QPixmap( textWidth, m_fontheight );
                textpixmap.fill( Qt::transparent );

                textpainter.begin( &textpixmap );

                if ( mark->selected() == 0 ) {
                    textpainter.setFont(font);
                    textpainter.setPen(m_labelcolor);
                    textpainter.drawText( 0, m_fontascent, mark->name() );
                }
                else {
                    drawLabelText(textpainter, mark, font, outlineWidth);
                }

                textpainter.end();
            }
            else {
                QImage textimage( textWidth, m_fontheight,
                                  QImage::Format_ARGB32_Premultiplied );
                textimage.fill( 0 );

                textpainter.begin( &textimage );

                if ( mark->selected() == 0 ) {
                    textpainter.setFont(font);
                    textpainter.setPen(m_labelcolor);
                    textpainter.drawText( 0, m_fontascent, mark->name() );
                }
                else {
                    drawLabelText(textpainter, mark, font, outlineWidth);
                }

                textpainter.end();

                textpixmap = QPixmap::fromImage( textimage );
            }

            mark->setTextPixmap( textpixmap );
        }

        // Finally save the label position on the map.
        // FIXME: This assumes that the hotspot is the center of the symbol.
        mark->setSymbolPos( QPoint( x - mark->symbolSize().width()  / 2,
                                    y - mark->symbolSize().height() / 2) );

        // Add the current placemark to the matching row and it's
        // direct neighbors.
        int idx = y / m_labelareaheight;
        if ( idx - 1 >= 0 )
            m_rowsection[ idx - 1 ].append( mark );
        m_rowsection[ idx ].append( mark );
        if ( idx + 1 < secnumber )
            m_rowsection[ idx + 1 ].append( mark );

        m_visiblePlacemarks.append(mark);
        labelnum ++;
        if ( labelnum >= maxlabels )
            break;
    }

    // qDebug() << QString("Size: %1, Rows: %2").arg(m_visiblePlacemarks.size()).arg( secnumber );
    PlaceMarkContainer::const_iterator  visit = m_visiblePlacemarks.constEnd();

    while ( visit != m_visiblePlacemarks.constBegin() ) {
        --visit;
        mark = *visit;
        //int tempSymbol = mark->symbolPos().x();
        //int tempText = mark->textRect().left();

        painter->drawPixmap( mark->textRect(),  mark->textPixmap() );
        painter->drawPixmap( mark->symbolPos(), mark->symbolPixmap() );
    }
}


void PlaceMarkPainter::rectangularPaintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    //int  imgwidth  = 2 * imgrx;
    //int  imgheight = 2 * imgry;
    int  x = 0;
    int  y = 0;

    int  secnumber = imgheight / m_labelareaheight + 1;
#if 0
      if ( mark->name().contains( "London" ) ){
      qDebug() << "London" << " y: " << QString::number( y ) << " qpos.v[Q_Y]: " << QString::number( qpos.v[Q_Y] );
      invplanetAxis.display();
      }
#endif
    // planetAxis.display();

    Quaternion  qpos;

    painter->setPen(QColor(Qt::black));

    QPainter    textpainter;

    QFont       font;

    const double outlineWidth = 2.5;
    int          textWidth = 0;

    PlaceMark*  firstMark = *(placecontainer->begin());
    const bool  noFilter = ( firstMark->population() == 0 
                             || ( firstMark->population() != 0
                                  && firstMark->role().isNull() ) ) 
                           ? true : false;

    QPixmap     textpixmap;

    // Calculate translation of center point
    double centerLat =  planetAxis.pitch() + M_PI;
    if ( centerLat > M_PI ) centerLat -= 2 * M_PI; 
    double centerLon =  planetAxis.yaw() + M_PI;

    double const xyFactor = 2 * viewParams->m_radius / M_PI;
    double degX;
    double degY;

    QVector< QVector< PlaceMark* > >  m_rowsection;
    for ( int i = 0; i < secnumber; i++)
        m_rowsection.append( QVector<PlaceMark*>( ) );

    if ( firstTime )
        m_visiblePlacemarks.clear();

    PlaceMark  *mark = 0;
    int         labelnum = 0;

    PlaceMarkContainer::const_iterator  it;
    for ( it = placecontainer->constBegin();
          it != placecontainer->constEnd();
          it++ )
    {
        mark  = *it; // no cast

#ifndef KML_GSOC
        if ( noFilter == false ) {
            if ( m_weightfilter.at( mark->popidx() ) > viewParams->m_radius
                 && mark->selected() == 0 )
                continue;
        }
        else {
            mark->setSymbol(21);
        }
#endif

        // Skip terrain marks if we're not showing terrain.
        if ( !viewParams->m_showTerrain
             && ( mark->symbol() >= 16 && mark->symbol() <= 20 ) )
            continue;

        // Skip city marks if we're not showing cities.
        if ( !viewParams->m_showCities
             && ( 0 <= mark->symbol() && mark->symbol() < 16 ) )
            continue;

        qpos = mark->quaternion();
        textpixmap = mark->textPixmap();

        // Let (x, y) be the position on the screen of the placemark..
        qpos.getSpherical( degX, degY );
        x = (int)(imgwidth  / 2 + xyFactor * (degX + centerLon));
        y = (int)(imgheight / 2 + xyFactor * (degY + centerLat));

        // Skip placemarks that are outside the screen area
        if ( ( ( x < 0 || x >= imgwidth )
               // FIXME: Carlos: check this:
               && x - 4 * viewParams->m_radius < 0
               && x + 4 * viewParams->m_radius >= imgwidth )
             || y < 0 || y >= imgheight )
        {
            mark->clearTextPixmap();
            continue;
        }

        // ----------------------------------------------------------------
        // End of checks. Here the actual painting starts.<commit_msg>Add a comment about a possible bug<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 <NAME> <<EMAIL>>"
// Copyright 2007      <NAME>  <<EMAIL>>"
//

#include "PlaceMarkPainter.h"

#include <QtCore/QAbstractItemModel>
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtCore/QPoint>
#include <QtCore/QVector>
#include <QtCore/QVectorIterator>
#include <QtGui/QIcon>
#include <QtGui/QPainter>

#include "global.h"
#include "PlaceMark.h"
#include "MarbleDirs.h"
#include "ViewParams.h"


// ================================================================
//                     class VisiblePlaceMark


class VisiblePlaceMark
{
 public:
    VisiblePlaceMark( PlaceMark *mark );
    ~VisiblePlaceMark();

    PlaceMark *placeMark() const                { return m_placeMark;  }
    void setPlaceMark( PlaceMark *_mark )       { m_placeMark = _mark; }

    const QPixmap  symbolPixmap() const { return m_placeMark->symbolPixmap();}
    const QSize    symbolSize()   const { return m_placeMark->symbolSize();  }

    const QPoint& symbolPos() const             { return m_symbolPos;   }
    void setSymbolPos( const QPoint& sympos )   { m_symbolPos = sympos; }
    void setSymbolPos( const int x, const int y ) {
	m_symbolPos = QPoint( x, y );
    }

    const QPixmap& labelPixmap() const          { return m_labelPixmap;       }
    void setLabelPixmap( QPixmap& labelPixmap ) { m_labelPixmap = labelPixmap;}

    void clearLabelPixmap() {
        if ( m_labelPixmap.isNull() == false )
            m_labelPixmap = QPixmap();
    }

    const QRect& labelRect() const              { return m_labelRect;    }
    void setLabelRect( const QRect& labelRect ) { m_labelRect = labelRect;}

 private:
    PlaceMark  *m_placeMark;	// the actual PlaceMark

    // View stuff
    QPoint      m_symbolPos;	// position of the placemark's symbol
    QPixmap     m_labelPixmap;	// the text label (most often name)
    QRect       m_labelRect;    // bounding box of label
};


VisiblePlaceMark::VisiblePlaceMark( PlaceMark *mark )
    : m_symbolPos(),
      m_labelPixmap(),
      m_labelRect()
{
    m_placeMark = mark;
}


VisiblePlaceMark::~VisiblePlaceMark()
{
}


// ================================================================
//                     class PlaceMarkPainter


static const int  maxlabels = 100;

PlaceMarkPainter::PlaceMarkPainter(QObject* parent)
    : QObject(parent),
      m_visiblePlacemarks(),
      m_visiblePlacemarksPool()
{
#ifdef Q_OS_MACX
    m_font_mountain = QFont( "Sans Serif",9, 50, false );

    m_font_regular           = QFont( "Sans Serif", 10, 50, false );
    m_font_regular_italics   = QFont( "Sans Serif", 10, 50, true );
    m_font_regular_underline = QFont( "Sans Serif", 10, 50, false );
#else
    m_font_mountain          = QFont( "Sans Serif",  7, 50, false );

    m_font_regular           = QFont( "Sans Serif",  8, 50, false );
    m_font_regular_italics   = QFont( "Sans Serif",  8, 50, true );
    m_font_regular_underline = QFont( "Sans Serif",  8, 50, false );
#endif

    m_font_regular_underline.setUnderline( true );

    m_fontheight = QFontMetrics( m_font_regular ).height();
    m_fontascent = QFontMetrics( m_font_regular ).ascent();

    m_labelareaheight = 2 * m_fontheight;

    m_labelcolor = QColor( 0, 0, 0, 255 );

    m_weightfilter
        << 9999
        << 4200
        << 3900
        << 3600

        << 3300
        << 3000
        << 2700
        << 2400

        << 2100
        << 1800
        << 1500
        << 1200

        << 900
        << 400
        << 200
        << 0;

    m_useXWorkaround = testXBug();
    qDebug() << "Use workaround: " << ( m_useXWorkaround ? "1" : "0" );
    // m_useXWorkaround = true;
}


#if 1

void PlaceMarkPainter::paintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    switch( viewParams->m_projection ) {
        case Spherical:
            sphericalPaintPlaceFolder(    painter, imgwidth, imgheight,
                                          viewParams, placecontainer,
                                          planetAxis, firstTime );
            break;
        case Equirectangular:
            rectangularPaintPlaceFolder(  painter, imgwidth, imgheight,
                                          viewParams, placecontainer,
                                          planetAxis, firstTime );
            break;
        default:
            qDebug()<<"Projection not supported";
    }

}

void PlaceMarkPainter::sphericalPaintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    //int  imgwidth  = 2 * imgrx;
    //int  imgheight = 2 * imgry;
    int  x = 0;
    int  y = 0;

    int  secnumber = imgheight / m_labelareaheight + 1;
#if 0
      if ( mark->name().contains( "London" ) ){
      qDebug() << "London" << " y: " << QString::number( y ) << " qpos.v[Q_Y]: " << QString::number( qpos.v[Q_Y] );
      invplanetAxis.display();
      }
#endif
    // planetAxis.display();

    Quaternion  invplanetAxis = planetAxis.inverse();
    Quaternion  qpos;

    painter->setPen(QColor(Qt::black));

    QPainter    textpainter;

    QFont       font;

    const double outlineWidth = 2.5;
    int          textWidth = 0;

    PlaceMark*  firstMark = *(placecontainer->begin());
    const bool  noFilter = ( firstMark->population() == 0 
                             || ( firstMark->population() != 0
                             && firstMark->role().isNull() ) ) 
                           ? true : false;

    QPixmap     textpixmap;

    QVector< QVector< PlaceMark* > >  m_rowsection;
    for ( int i = 0; i < secnumber; i++)
        m_rowsection.append( QVector<PlaceMark*>( ) );

    if ( firstTime )
        m_visiblePlacemarks.clear();

    PlaceMark  *mark = 0;
    int         labelnum = 0;
    PlaceMarkContainer::const_iterator  it;
    for ( it = placecontainer->constBegin();
          it != placecontainer->constEnd();
          it++ )
    {
        mark  = *it; // no cast

        // Skip the places that are too small.
        if ( noFilter == false ) {
            if ( m_weightfilter.at( mark->popidx() ) > viewParams->m_radius
                 && mark->selected() == 0 )
                continue;
        }
        else {
            mark->setSymbol(21);
        }

        // Skip terrain marks if we're not showing terrain.
        if ( !viewParams->m_showTerrain
             && ( mark->symbol() >= 16 && mark->symbol() <= 20 ) )
            continue;

        // Skip city marks if we're not showing cities.
        if ( !viewParams->m_showCities
             && ( mark->symbol() >= 0 && mark->symbol() < 16 ) )
            continue;

        qpos       = mark->quaternion();
        textpixmap = mark->textPixmap();
        qpos.rotateAroundAxis(invplanetAxis);

        // Skip placemarks at the other side of the earth.
        if ( qpos.v[Q_Z] < 0 ) {
            // FIXME: Should this be removed here or inserted in all
            //        the other skips like this?
            mark->clearTextPixmap();
            continue;
        }

        // Let (x, y) be the position on the screen of the placemark..
        x = (int)(imgwidth  / 2 + viewParams->m_radius * qpos.v[Q_X]);
        y = (int)(imgheight / 2 + viewParams->m_radius * qpos.v[Q_Y]);

        // Skip placemarks that are outside the screen area
        if ( x < 0 || x >= imgwidth || y < 0 || y >= imgheight ) {
            mark->clearTextPixmap();
            continue;
        }

        // ----------------------------------------------------------------
        // End of checks. Here the actual painting starts.

        // Choose Section
        const QVector<PlaceMark*>  currentsec = m_rowsection.at( y / m_labelareaheight );

        // Specify font properties
        if ( textpixmap.isNull() ) {
            labelFontData( mark, outlineWidth,
                           font, textWidth );
        }
        else {
            textWidth = ( mark->textRect() ).width();
        }

        // Find out whether the area around the placemark is covered already.
        if ( !roomForLabel( currentsec, mark,
                            textWidth, x, y ) )
        {
            // Don't clear the text pixmap here, for the label should
            // really be painted, but there is just too many other
            // labels around it so there is no room.
            continue;
        }

        // Paint the label
        if ( textpixmap.isNull() ) {
            // Draw the text on the label.

            // Due to some XOrg bug this requires a workaround via
            // QImage in some cases.

            if ( !m_useXWorkaround ) {
                textpixmap = QPixmap( textWidth, m_fontheight );
                textpixmap.fill( Qt::transparent );

                textpainter.begin( &textpixmap );

                if ( mark->selected() == 0 ) {
                    textpainter.setFont(font);
                    textpainter.setPen(m_labelcolor);
                    textpainter.drawText( 0, m_fontascent, mark->name() );
                }
                else {
                    drawLabelText(textpainter, mark, font, outlineWidth);
                }

                textpainter.end();
            }
            else {
                QImage textimage( textWidth, m_fontheight,
                                  QImage::Format_ARGB32_Premultiplied );
                textimage.fill( 0 );

                textpainter.begin( &textimage );

                if ( mark->selected() == 0 ) {
                    textpainter.setFont(font);
                    textpainter.setPen(m_labelcolor);
                    textpainter.drawText( 0, m_fontascent, mark->name() );
                }
                else {
                    drawLabelText(textpainter, mark, font, outlineWidth);
                }

                textpainter.end();

                textpixmap = QPixmap::fromImage( textimage );
            }

            mark->setTextPixmap( textpixmap );
        }

        // Finally save the label position on the map.
        // FIXME: This assumes that the hotspot is the center of the symbol.
        mark->setSymbolPos( QPoint( x - mark->symbolSize().width()  / 2,
                                    y - mark->symbolSize().height() / 2) );

        // Add the current placemark to the matching row and it's
        // direct neighbors.
        int idx = y / m_labelareaheight;
        if ( idx - 1 >= 0 )
            m_rowsection[ idx - 1 ].append( mark );
        m_rowsection[ idx ].append( mark );
        if ( idx + 1 < secnumber )
            m_rowsection[ idx + 1 ].append( mark );

        m_visiblePlacemarks.append(mark);
        labelnum ++;
        if ( labelnum >= maxlabels )
            break;
    }

    // qDebug() << QString("Size: %1, Rows: %2").arg(m_visiblePlacemarks.size()).arg( secnumber );
    PlaceMarkContainer::const_iterator  visit = m_visiblePlacemarks.constEnd();

    while ( visit != m_visiblePlacemarks.constBegin() ) {
        --visit;
        mark = *visit;
        //int tempSymbol = mark->symbolPos().x();
        //int tempText = mark->textRect().left();

        painter->drawPixmap( mark->textRect(),  mark->textPixmap() );
        painter->drawPixmap( mark->symbolPos(), mark->symbolPixmap() );
    }
}


void PlaceMarkPainter::rectangularPaintPlaceFolder(QPainter* painter,
                                        int imgwidth, int imgheight,
                                        ViewParams *viewParams,
                                        const PlaceMarkContainer* placecontainer,
                                        Quaternion planetAxis,
                                        bool firstTime )
{
    int  x = 0;
    int  y = 0;

    int  secnumber = imgheight / m_labelareaheight + 1;
#if 0
      if ( mark->name().contains( "London" ) ){
      qDebug() << "London" << " y: " << QString::number( y ) << " qpos.v[Q_Y]: " << QString::number( qpos.v[Q_Y] );
      invplanetAxis.display();
      }
#endif
    // planetAxis.display();

    Quaternion  qpos;

    painter->setPen(QColor(Qt::black));

    QPainter    textpainter;

    QFont       font;

    const double outlineWidth = 2.5;
    int          textWidth = 0;

    PlaceMark*  firstMark = *(placecontainer->begin());
    const bool  noFilter = ( firstMark->population() == 0 
                             || ( firstMark->population() != 0
                                  && firstMark->role().isNull() ) ) 
                           ? true : false;

    QPixmap     textpixmap;

    // Calculate translation of center point
    double centerLat =  planetAxis.pitch() + M_PI;
    if ( centerLat > M_PI ) centerLat -= 2 * M_PI; 
    double centerLon =  planetAxis.yaw() + M_PI;

    double const xyFactor = 2 * viewParams->m_radius / M_PI;
    double degX;
    double degY;

    QVector< QVector< PlaceMark* > >  m_rowsection;
    for ( int i = 0; i < secnumber; i++)
        m_rowsection.append( QVector<PlaceMark*>( ) );

    if ( firstTime )
        m_visiblePlacemarks.clear();

    PlaceMark  *mark = 0;
    int         labelnum = 0;

    PlaceMarkContainer::const_iterator  it;
    for ( it = placecontainer->constBegin();
          it != placecontainer->constEnd();
          it++ )
    {
        mark  = *it; // no cast

#ifndef KML_GSOC
        if ( noFilter == false ) {
            if ( m_weightfilter.at( mark->popidx() ) > viewParams->m_radius
                 && mark->selected() == 0 )
                continue;
        }
        else {
            mark->setSymbol(21);
        }
#endif

        // Skip terrain marks if we're not showing terrain.
        if ( !viewParams->m_showTerrain
             && ( mark->symbol() >= 16 && mark->symbol() <= 20 ) )
            continue;

        // Skip city marks if we're not showing cities.
        if ( !viewParams->m_showCities
             && ( 0 <= mark->symbol() && mark->symbol() < 16 ) )
            continue;

        qpos = mark->quaternion();
        textpixmap = mark->textPixmap();

        // Let (x, y) be the position on the screen of the placemark..
        qpos.getSpherical( degX, degY );
        x = (int)(imgwidth  / 2 + xyFactor * (degX + centerLon));
        y = (int)(imgheight / 2 + xyFactor * (degY + centerLat));

        // Skip placemarks that are outside the screen area
        //
        // FIXME: I have the feeling that this is wrong, because there
        //        are always insanely few placemarks on the flat map 
        //        compared to the globe.
        if ( ( ( x < 0 || x >= imgwidth )
               // FIXME: Carlos: check this:
               && x - 4 * viewParams->m_radius < 0
               && x + 4 * viewParams->m_radius >= imgwidth )
             || y < 0 || y >= imgheight )
        {
            mark->clearTextPixmap();
            continue;
        }

        // ----------------------------------------------------------------
        // End of checks. Here the actual painting starts.
{'fraction_non_alphanumeric': 0.1265826832075713, 'fraction_numerical': 0.011958050901649827, 'mean_word_length': 1.6208312384782972, 'pattern_counts': {'":': 0, '<': 193, '<?xml version=': 0, '>': 207, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 64, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3717644', 'n_tokens_mistral': 9390, 'n_tokens_neox': 8654, 'n_words': 2255}