#ifndef MAPSFORGE_RASTERTILE_H #define MAPSFORGE_RASTERTILE_H #include #include "map/projection.h" #include "map/transform.h" #include "map/textpointitem.h" #include "map/textpathitem.h" #include "map/matrix.h" #include "style.h" #include "mapdata.h" #define HILLSHADING_RENDER(ptr) \ static_cast(ptr) #define PATH_RENDER(ptr) \ static_cast(ptr) #define POINT_RENDER(ptr) \ static_cast(ptr) namespace Mapsforge { class RasterTile { public: RasterTile(const Projection &proj, const Transform &transform, const Style *style, MapData *data, int zoom, const QRect &rect, qreal ratio, bool hillShading) : _proj(proj), _transform(transform), _style(style), _data(data), _zoom(zoom), _rect(rect), _ratio(ratio), _hillShading(hillShading) {} int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} const QPixmap &pixmap() const {return _pixmap;} void render(); private: struct PainterPath { PainterPath() : path(0) {} QPainterPath pp; const MapData::Path *path; }; struct Label { Label(const MapData::Point *p, const QByteArray *lbl, const Style::Symbol *si, const Style::TextRender *ti) : point(p), lbl(lbl), ti(ti), si(si) { Q_ASSERT(si || ti); } bool operator<(const Label &other) const { if (priority() == other.priority()) return point->id < other.point->id; else return (priority() > other.priority()); } int priority() const {return si ? si->priority() : ti->priority();} const MapData::Point *point; const QByteArray *lbl; const Style::TextRender *ti; const Style::Symbol *si; }; struct LineLabel { LineLabel(const PainterPath *p, const QByteArray *lbl, const Style::Symbol *si, const Style::TextRender *ti) : path(p), lbl(lbl), ti(ti), si(si) { Q_ASSERT(si || ti); } bool operator<(const LineLabel &other) const { return (priority() > other.priority()); } int priority() const {return si ? si->priority() : ti->priority();} const PainterPath *path; const QByteArray *lbl; const Style::TextRender *ti; const Style::Symbol *si; }; class RenderInstruction { public: RenderInstruction() : _render(0), _path(0), _point(0) {} RenderInstruction(const Style::PathRender *render, PainterPath *path) : _render(render), _path(path), _point(0) {} RenderInstruction(const Style::CircleRender *render, const MapData::Point *point) : _render(render), _path(0), _point(point) {} RenderInstruction(const Style::HillShadingRender *render) : _render(render), _path(0), _point(0) {} bool operator<(const RenderInstruction &other) const { if (layer() == other.layer()) return zOrder() < other.zOrder(); else return (layer() < other.layer()); } const Style::PathRender *pathRender() const {return PATH_RENDER(_render);} const Style::CircleRender *circleRender() const {return POINT_RENDER(_render);} const Style::HillShadingRender *hillShadingRender() const {return HILLSHADING_RENDER(_render);} PainterPath *path() const {return _path;} const MapData::Point *point() const {return _point;} private: int layer() const { if (_path) return _path->path->point.layer; else if (_point) return _point->layer; else return HILLSHADING_RENDER(_render)->layer(); } int zOrder() const { if (_path) return PATH_RENDER(_render)->zOrder(); else if (_point) return POINT_RENDER(_render)->zOrder(); else return HILLSHADING_RENDER(_render)->zOrder(); } const Style::Render *_render; PainterPath *_path; const MapData::Point *_point; }; struct PathKey { PathKey(int zoom, bool closed, const QVector &tags) : zoom(zoom), closed(closed), tags(tags) {} bool operator==(const PathKey &other) const { return zoom == other.zoom && closed == other.closed && tags == other.tags; } int zoom; bool closed; const QVector &tags; }; struct PointKey { PointKey(int zoom, const QVector &tags) : zoom(zoom), tags(tags) {} bool operator==(const PointKey &other) const { return zoom == other.zoom && tags == other.tags; } int zoom; const QVector &tags; }; class PointItem : public TextPointItem { public: PointItem(const QPoint &point, const QByteArray *label, const QFont *font, const QImage *img, const QColor *color, const QColor *haloColor) : TextPointItem(point, label ? new QString(*label) : 0, font, img, color, haloColor, 0) {} PointItem(const QPoint &point, const QByteArray *label, const QFont *font, const QColor *color, const QColor *bgColor) : TextPointItem(point, label ? new QString(*label) : 0, font, 0, color, 0, bgColor) {} ~PointItem() {delete _text;} }; class PathItem : public TextPathItem { public: PathItem(const QPainterPath &line, const QByteArray *label, const QImage *img, const QRect &tileRect, const QFont *font, const QColor *color, const QColor *haloColor, bool rotate) : TextPathItem(line, label ? new QString(*label) : 0, tileRect, font, color, haloColor, img, rotate) {} ~PathItem() {delete _text;} }; friend HASH_T qHash(const RasterTile::PathKey &key); friend HASH_T qHash(const RasterTile::PointKey &key); void fetchData(QList &paths, QList &points) const; void pathInstructions(const QList &paths, QVector &painterPaths, QVector &instructions) const; void circleInstructions(const QList &points, QVector &instructions) const; void hillShadingInstructions( QVector &instructions) const; QPointF ll2xy(const Coordinates &c) const {return _transform.proj2img(_proj.ll2xy(c));} Coordinates xy2ll(const QPointF &p) const {return _proj.xy2ll(_transform.img2proj(p));} void processLabels(const QList &points, QList &textItems) const; void processLineLabels(const QVector &paths, QList &textItems) const; QPainterPath painterPath(const Polygon &polygon, bool curve) const; void drawTextItems(QPainter *painter, const QList &textItems); void drawPaths(QPainter *painter, const QList &paths, const QList &points, QVector &painterPaths); MatrixD elevation(int extend) const; Projection _proj; Transform _transform; const Style *_style; MapData *_data; int _zoom; QRect _rect; qreal _ratio; QPixmap _pixmap; bool _hillShading; }; inline HASH_T qHash(const RasterTile::PathKey &key) { return ::qHash(key.zoom) ^ ::qHash(key.tags); } inline HASH_T qHash(const RasterTile::PointKey &key) { return ::qHash(key.zoom) ^ ::qHash(key.tags); } } #endif // MAPSFORGE_RASTERTILE_H