Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,44 @@ Only local BRouter supports fast (on-the-fly) routing. Online BRouter and Routin

---

## Architecture: CMapIMG Blend2D hybrid renderer

`CMapIMG::draw()` (the Garmin IMG renderer) rasterises geometry with **Blend2D** and
keeps **text/labels on QPainter**. Dependency: `find_package(blend2d REQUIRED)` (root
CMakeLists), linked as `blend2d::blend2d`.

**Phase split in `draw()`:**
1. *Geometry phase (Blend2D):* `drawPolygons`, `drawPolylines`, `drawPoints`, `drawPois`,
`loadVisibleData` — all take `BLContext&`. They also collect text into `textpaths`/`labels`.
2. *Text phase (QPainter):* `drawText`, `drawLabels` — still take `QPainter&`. Qt's font
matching/shaping has no Blend2D equivalent and text is a negligible share of draw time.

**Key invariants (easy to break):**
- **Premultiplied round-trip.** The shared buffer is `Format_ARGB32` (non-premultiplied);
Blend2D only renders `BL_FORMAT_PRGB32`. `draw()` does `convertTo(Format_ARGB32_Premultiplied)`
at the start and `convertTo(Format_ARGB32)` at the end so the format change stays invisible
to the rest of the map stack. (Optional follow-up: make `IDrawContext` allocate premultiplied
buffers to drop both conversions.)
- **Synchronous context only.** `BLContext(blBuf)` defaults to synchronous rendering, so source
images for blits (`img2line` segments, icons) and pattern tiles may be temporaries — they are
read before the call returns. Do **not** switch to a multithreaded/async `BLContextCreateInfo`
without making those sources outlive `ctx.end()`.
- **`ctx.end()` before the QPainter phase** — flushes Blend2D pixels before QPainter touches the
same image.
- **Both phases re-apply `translate(-pp)`** (the buffer-vs-screen offset); the single shared
painter that used to do it once is gone.

**Helpers (anonymous namespace in `CMapIMG.cpp`):** `applyPen` (QPen→stroke state incl. Qt dash
styles, returns false for `Qt::NoPen`), `polyToPath`, `toBLColor`, `blitQImage`/`blitBullet`
(convert to premultiplied on the fly), `brushToTile` (texture/hatch QBrush → repeating `BLPattern`
tile). `drawPolygons` sets `BL_FILL_RULE_EVEN_ODD` to match `QPainter::drawPolygon`.

The pixmap-along-line loop indexes polyline vertices directly (arc-length breakpoints coincide
with vertices), replacing the old `QPainterPath::pointAtPercent` walk; angles use `std::atan2`
(radians) since `BLContext::rotate` takes radians, not degrees.

---

## Architecture: tree item delegates

The three `QStyledItemDelegate` subclasses used by the tree views:
Expand Down
44 changes: 44 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,50 @@ endif(NOT ALGLIB_FOUND AND BUILD_QMAPSHACK)

add_definitions(-DHELPPATH=${HTML_INSTALL_DIR})

include(FetchContent)

###############################################################################################
# Get Tracy
###############################################################################################
set(TRACY_GIT_TAG "master" CACHE STRING "Tracy git revision to fetch")
FetchContent_Declare (
tracy
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)

###############################################################################################
# Get Blend2D and it's dependency AsmJit
###############################################################################################
set(ASMJIT_GIT_TAG "master" CACHE STRING "AsmJit git revision to fetch")
set(BLEND2D_GIT_TAG "master" CACHE STRING "Blend2D git revision to fetch")

# asmjit is Blend2D's JIT backend. Fetch its sources only: SOURCE_SUBDIR points at a
# directory with no CMakeLists.txt so FetchContent_MakeAvailable populates without calling
# add_subdirectory(). Blend2D adds asmjit itself (via ASMJIT_DIR) and, because we build it
# statically, embeds it directly into the blend2d library.
FetchContent_Declare(asmjit
GIT_REPOSITORY https://github.com/asmjit/asmjit.git
GIT_TAG ${ASMJIT_GIT_TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
SOURCE_SUBDIR __populate_only__
)
FetchContent_MakeAvailable(asmjit)
set(ASMJIT_DIR "${asmjit_SOURCE_DIR}" CACHE PATH "AsmJit source directory" FORCE)

set(BLEND2D_STATIC TRUE)
FetchContent_Declare(blend2d
GIT_REPOSITORY https://github.com/blend2d/blend2d.git
GIT_TAG ${BLEND2D_GIT_TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(blend2d)

###############################################################################################
# Create library from Garmin's FIT SDK
###############################################################################################
Expand Down
2 changes: 2 additions & 0 deletions src/qmapshack/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ target_link_libraries(${APPLICATION_NAME}
${ALGLIB_LIBRARIES}
QuaZip::QuaZip
GarminFit
Tracy::TracyClient
blend2d::blend2d
)

if(APPLE)
Expand Down
2 changes: 2 additions & 0 deletions src/qmapshack/canvas/IDrawContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "canvas/IDrawContext.h"

#include <QtWidgets>
#include <tracy/Tracy.hpp>

#define BUFFER_BORDER 50

Expand Down Expand Up @@ -258,6 +259,7 @@ void IDrawContext::convertPx2Rad(QPointF& p) const {
}

void IDrawContext::convertRad2Px(QPointF& p) const {
ZoneScoped;
mutex.lock(); // --------- start serialize with thread

QPointF f = focus;
Expand Down
3 changes: 3 additions & 0 deletions src/qmapshack/map/CMapDraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <QtGui>
#include <QtWidgets>
#include <tracy/Tracy.hpp>

#include "CMainWindow.h"
#include "canvas/CCanvas.h"
Expand Down Expand Up @@ -405,9 +406,11 @@ void CMapDraw::drawt(IDrawContext::buffer_t& currentBuffer) /* override */
}

item->setProcessing(true);
FrameMarkStart("imgDraw");
item->getMapfile()->draw(currentBuffer);
item->setProcessing(false);
seenActiveMap = true;
FrameMarkEnd("imgDraw");
}
}
CMapItem::mutexActiveMaps.unlock();
Expand Down
Loading