Skip to content

Commit

Permalink
Simplify and fix kerning of curved text
Browse files Browse the repository at this point in the history
  • Loading branch information
10110111 committed Dec 14, 2024
1 parent f717a78 commit 8ed9545
Showing 1 changed file with 34 additions and 66 deletions.
100 changes: 34 additions & 66 deletions src/core/StelPainter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,84 +575,52 @@ void StelPainter::sSphereMap(double radius, unsigned int slices, unsigned int st
}
}

void StelPainter::drawTextGravity180(float x, float y, const QString& ws, float xshift, float yshift)
void StelPainter::drawTextGravity180(const float x, const float y, const QString& ws, const float xshift, const float yshift)
{
const float dx = x - static_cast<float>(prj->viewportCenter[0]);
const float dy = y - static_cast<float>(prj->viewportCenter[1]);
const float d = std::sqrt(dx*dx + dy*dy);
const float limit = 120.;
float d = std::sqrt(dx*dx + dy*dy);

// If the text is too far away to be visible in the screen return
if (d>qMax(prj->viewportXywh[3], prj->viewportXywh[2])*2 || ws.isEmpty())
return;

const auto fm = getFontMetrics();
const bool rtl = StelApp::getInstance().getLocaleMgr().isSkyRTL();

const float ppx = static_cast<float>(prj->getDevicePixelsPerPixel());
const float cWidth = static_cast<float>(getFontMetrics().boundingRect(ws).width())/ws.length(); // average character width
const float stdWidth = static_cast<float>(getFontMetrics().boundingRect("n").width());
const float theta_o = M_PIf + std::atan2(dx, dy - 1);
float anglePerUnitWidth = ppx / d;
float theta = std::atan2(dy - 1, dx);
float psi = std::atan2(ppx*cWidth*1.2, d + 1) * M_180_PIf; // Factor 1.2 is empirical.
if (psi>5)
psi = 5;

const float xVc = static_cast<float>(prj->viewportCenter[0]) + xshift;
const float yVc = static_cast<float>(prj->viewportCenter[1]) + yshift;
const float cosr = std::cos(-theta_o * M_PI_180f);
const float sinr = std::sin(-theta_o * M_PI_180f);
float xom = x + xshift*cosr - yshift*sinr;
float yom = y + yshift*sinr + xshift*cosr;
float width;
QChar s;

if (!StelApp::getInstance().getLocaleMgr().isSkyRTL())
{
for (int i=0; i<ws.length(); ++i)
{
s = ws[i];
if (d<limit)
{
drawText(xom, yom, s, -theta_o*M_180_PIf+psi*static_cast<float>(i), 0., 0.);
xom += cWidth*std::cos(-theta_o+psi*static_cast<float>(i) * M_PI_180f);
yom += cWidth*std::sin(-theta_o+psi*static_cast<float>(i) * M_PI_180f);
}
else
{
x = d * std::cos(theta) + xVc ;
y = d * std::sin(theta) + yVc ;
drawText(x, y, s, 90.f + theta*M_180_PIf, 0., 0.);
// Compute how much the character contributes to the angle
if (s.isSpace())
width = stdWidth;
else
width = static_cast<float>(getFontMetrics().boundingRect(s).width());
theta += psi * M_PI_180f * (1 + (width - cWidth)/ cWidth);
}
}

float xVc = static_cast<float>(prj->viewportCenter[0]) + xshift;
float yVc = static_cast<float>(prj->viewportCenter[1]) + yshift;

const float charWidth = fm.averageCharWidth();
constexpr float maxAnglePerChar = 10 * M_PI_180f;
if (charWidth * anglePerUnitWidth > maxAnglePerChar)
{
// Too curvy text, limit its curvature by moving the center of curvature away
const float x0 = d * std::cos(theta) + xVc;
const float y0 = d * std::sin(theta) + yVc;

anglePerUnitWidth = maxAnglePerChar / charWidth;
d = ppx / anglePerUnitWidth;

xVc = x0 - d * std::cos(theta);
yVc = y0 - d * std::sin(theta);
}
else

const int slen = ws.length();
const int startI = rtl ? slen - 1 : 0;
const int endI = rtl ? -1 : slen;
const int inc = rtl ? -1 : 1;
for (int i = startI; i != endI; i += inc)
{
int slen = ws.length();
for (int i=0;i<slen;i++)
{
s = ws[slen-1-i];
if (d<limit)
{
drawText(xom, yom, s, -theta_o*M_180_PIf+psi*static_cast<float>(i), 0., 0.);
xom += cWidth*std::cos(-theta_o+psi*static_cast<float>(i) * M_PI_180f);
yom += cWidth*std::sin(-theta_o+psi*static_cast<float>(i) * M_PI_180f);
}
else
{
x = d * std::cos(theta) + xVc;
y = d * std::sin(theta) + yVc;
drawText(x, y, s, 90.f + theta*M_180_PIf, 0., 0.);
if (s.isSpace())
width = stdWidth;
else
width = static_cast<float>(getFontMetrics().boundingRect(s).width());
theta += psi * M_PI_180f * (1 + (width - cWidth)/ cWidth);
}
}
const QChar c = ws[i];
const float x = d * std::cos(theta) + xVc;
const float y = d * std::sin(theta) + yVc;
drawText(x, y, c, 90.f + theta*M_180_PIf, 0., 0.);
theta += fm.horizontalAdvance(c) * anglePerUnitWidth;
}
}

Expand Down

0 comments on commit 8ed9545

Please sign in to comment.