forked from organicmaps/organicmaps
path_renderer: butt caps, square caps, bevel linejoins
This commit is contained in:
parent
3bdcacf169
commit
12852f1d21
3 changed files with 145 additions and 53 deletions
|
@ -87,12 +87,15 @@ namespace
|
|||
double width = 2,
|
||||
double depth = 0,
|
||||
double pathOffset = 0,
|
||||
double penOffset = 0)
|
||||
double penOffset = 0,
|
||||
graphics::Pen::Info::ELineCap lineCap = graphics::Pen::Info::ERoundCap,
|
||||
graphics::Pen::Info::ELineJoin lineJoin = graphics::Pen::Info::ERoundJoin
|
||||
)
|
||||
{
|
||||
m_pathes.push_back(points);
|
||||
m_pathOffsets.push_back(pathOffset);
|
||||
//m_patterns.push_back(pattern);
|
||||
m_penInfos.push_back(graphics::Pen::Info(color, width, pattern.empty() ? 0 : &pattern[0], pattern.size(), penOffset));
|
||||
m_penInfos.push_back(graphics::Pen::Info(color, width, pattern.empty() ? 0 : &pattern[0], pattern.size(), penOffset, 0, 0, lineJoin, lineCap));
|
||||
m_depthes.push_back(depth);
|
||||
}
|
||||
|
||||
|
@ -539,29 +542,78 @@ namespace
|
|||
void Init()
|
||||
{
|
||||
base_t::Init();
|
||||
m_drawAxis = true;
|
||||
|
||||
std::vector<m2::PointD> testPoints;
|
||||
std::vector<double> testPattern;
|
||||
double dx = 0, dy = 0, width = 30;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
|
||||
// testPoints.push_back(m2::PointD(120, 200));
|
||||
// testPoints.push_back(m2::PointD(180, 140));
|
||||
testPoints.push_back(m2::PointD(220, 269));
|
||||
testPoints.push_back(m2::PointD(320, 270));
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::EButtCap, graphics::Pen::Info::ERoundJoin);
|
||||
|
||||
AddTest(testPoints, testPattern, graphics::Color(255, 0, 0, 255), 40);
|
||||
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
dy += 130;
|
||||
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(420, 300));
|
||||
testPoints.push_back(m2::PointD(480, 240));
|
||||
testPoints.push_back(m2::PointD(520, 369));
|
||||
testPoints.push_back(m2::PointD(620, 370));
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::ESquareCap, graphics::Pen::Info::ERoundJoin);
|
||||
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), 40);
|
||||
dy += 130;
|
||||
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::ERoundCap, graphics::Pen::Info::ERoundJoin);
|
||||
|
||||
|
||||
dy = 0;
|
||||
dx += 200;
|
||||
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::EButtCap, graphics::Pen::Info::EBevelJoin);
|
||||
|
||||
|
||||
dy += 130;
|
||||
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::ESquareCap, graphics::Pen::Info::EBevelJoin);
|
||||
|
||||
dy += 130;
|
||||
|
||||
testPoints.clear();
|
||||
testPoints.push_back(m2::PointD(dx + 20, dy + 100));
|
||||
testPoints.push_back(m2::PointD(dx + 80, dy + 40));
|
||||
testPoints.push_back(m2::PointD(dx + 120, dy + 169));
|
||||
testPoints.push_back(m2::PointD(dx + 220, dy + 170));
|
||||
AddTest(testPoints, testPattern, graphics::Color(0, 255, 0, 255), width, 0, 0, 0, graphics::Pen::Info::ERoundCap, graphics::Pen::Info::EBevelJoin);
|
||||
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
testPattern.push_back(20);
|
||||
|
||||
dx += 200;
|
||||
dy = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1410,9 +1462,9 @@ namespace
|
|||
UNIT_TEST_GL(TestDrawPathWithOffset);
|
||||
UNIT_TEST_GL(TestDrawPathJoin);
|
||||
UNIT_TEST_GL(TestDrawPathSolid1PX);
|
||||
UNIT_TEST_GL(TestDrawPathSolid2PX);
|
||||
UNIT_TEST_GL(TestDrawPathSolid2PX);*/
|
||||
UNIT_TEST_GL(TestDrawPathSolid);
|
||||
UNIT_TEST_GL(TestDrawOverlappedSymbolWithText);
|
||||
/*UNIT_TEST_GL(TestDrawOverlappedSymbolWithText);
|
||||
UNIT_TEST_GL(TestDrawAnyRect);
|
||||
UNIT_TEST_GL(TestDrawSector);
|
||||
UNIT_TEST_GL(TestDrawPathSolidDiffWidth);
|
||||
|
@ -1422,6 +1474,6 @@ namespace
|
|||
UNIT_TEST_GL(TestDrawUtilsRect);
|
||||
UNIT_TEST_GL(TestDrawUtilsRectFilledTexture);
|
||||
UNIT_TEST_GL(TestDrawSymbolFiltering);
|
||||
UNIT_TEST_GL(TestDrawCircle);*/
|
||||
UNIT_TEST_GL(TestDrawImage);
|
||||
UNIT_TEST_GL(TestDrawCircle);
|
||||
UNIT_TEST_GL(TestDrawImage);*/
|
||||
}
|
||||
|
|
|
@ -140,11 +140,10 @@ namespace graphics
|
|||
|
||||
m2::PointF coords[4] =
|
||||
{
|
||||
// vng: i think this "rawTileStartPt + fNorm" reading better, isn't it?
|
||||
m2::PointF(rawTileStartPt.x + fNorm.x, rawTileStartPt.y + fNorm.y),
|
||||
m2::PointF(rawTileStartPt.x - fNorm.x, rawTileStartPt.y - fNorm.y),
|
||||
m2::PointF(rawTileEndPt.x - fNorm.x, rawTileEndPt.y - fNorm.y),
|
||||
m2::PointF(rawTileEndPt.x + fNorm.x, rawTileEndPt.y + fNorm.y)
|
||||
rawTileStartPt + fNorm,
|
||||
rawTileStartPt - fNorm,
|
||||
rawTileEndPt - fNorm,
|
||||
rawTileEndPt + fNorm
|
||||
};
|
||||
|
||||
m2::PointF texCoords[4] =
|
||||
|
@ -255,10 +254,17 @@ namespace graphics
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void PathRenderer::drawSolidPath(m2::PointD const * points, size_t pointsCount, double offset, Pen const * pen, double depth)
|
||||
{
|
||||
ASSERT(pen->m_isSolid, ());
|
||||
|
||||
bool const hasRoundCap = (pen->m_info.m_cap == pen->m_info.ERoundCap);
|
||||
bool const hasSquareCap = (pen->m_info.m_cap == pen->m_info.ESquareCap);
|
||||
bool const hasRoundJoin = (pen->m_info.m_join == pen->m_info.ERoundJoin);
|
||||
bool const hasBevelJoin = (pen->m_info.m_join == pen->m_info.EBevelJoin);
|
||||
|
||||
|
||||
for (size_t i = 0; i < pointsCount - 1; ++i)
|
||||
{
|
||||
m2::PointD dir = points[i + 1] - points[i];
|
||||
|
@ -281,27 +287,46 @@ namespace graphics
|
|||
m2::PointF const fDir(fNorm.y, -fNorm.x);
|
||||
|
||||
int numPoints = 4;
|
||||
bool const hasLeftRoundCap = (pen->m_info.m_cap == pen->m_info.ERoundCap) || (i != 0);
|
||||
bool const hasRightRoundCap = (pen->m_info.m_cap == pen->m_info.ERoundCap) || (i != (pointsCount - 2));
|
||||
if (hasLeftRoundCap) {numPoints += 2;};
|
||||
if (hasRightRoundCap) {numPoints += 2;};
|
||||
|
||||
int j = 0;
|
||||
bool const leftIsCap = i == 0;
|
||||
bool const rightIsCap = i == (pointsCount - 2);
|
||||
|
||||
if (leftIsCap && (hasRoundCap || hasSquareCap))
|
||||
numPoints += 2;
|
||||
if ((rightIsCap && (hasRoundCap || hasSquareCap)) || (!rightIsCap && (hasRoundJoin || hasBevelJoin)))
|
||||
numPoints += 2;
|
||||
|
||||
|
||||
int cur = 0;
|
||||
|
||||
m2::PointF coords[numPoints];
|
||||
if (hasLeftRoundCap)
|
||||
|
||||
if (leftIsCap && (hasRoundCap || hasSquareCap))
|
||||
{
|
||||
coords[j] = points[i] - fDir + fNorm; j++;
|
||||
coords[j] = points[i] - fDir - fNorm; j++;
|
||||
coords[cur++] = points[i] - fDir + fNorm;
|
||||
coords[cur++] = points[i] - fDir - fNorm;
|
||||
}
|
||||
coords[j] = points[i] + fNorm; j++;
|
||||
coords[j] = points[i] - fNorm; j++;
|
||||
coords[j] = nextPt + fNorm; j++;
|
||||
coords[j] = nextPt - fNorm; j++;
|
||||
if (hasRightRoundCap)
|
||||
|
||||
coords[cur++] = points[i] + fNorm;
|
||||
coords[cur++] = points[i] - fNorm;
|
||||
coords[cur++] = nextPt + fNorm;
|
||||
coords[cur++] = nextPt - fNorm;
|
||||
|
||||
if ((rightIsCap && (hasRoundCap || hasSquareCap)) || (!rightIsCap && hasRoundJoin))
|
||||
{
|
||||
coords[j] = nextPt + fDir + fNorm; j++;
|
||||
coords[j] = nextPt + fDir - fNorm; j++;
|
||||
coords[cur++] = nextPt + fDir + fNorm;
|
||||
coords[cur++] = nextPt + fDir - fNorm;
|
||||
}
|
||||
else if (!rightIsCap && hasBevelJoin)
|
||||
{
|
||||
m2::PointD dirNextSeg = points[i + 2] - points[i + 1];
|
||||
double lenNextSeg = dirNextSeg.Length(m2::PointD(0, 0));
|
||||
dirNextSeg *= 1.0 / lenNextSeg;
|
||||
m2::PointD normNextSeg(-dirNextSeg.y, dirNextSeg.x);
|
||||
m2::PointF const fNormNextSeg = normNextSeg * geomHalfWidth;
|
||||
|
||||
coords[cur++] = points[i + 1] + fNormNextSeg;
|
||||
coords[cur++] = points[i + 1] - fNormNextSeg;
|
||||
}
|
||||
|
||||
GeometryPipeline & p = pipeline(pen->m_pipelineID);
|
||||
|
@ -314,22 +339,36 @@ namespace graphics
|
|||
return;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
m2::PointF texCoords[numPoints];
|
||||
if (hasLeftRoundCap)
|
||||
cur = 0;
|
||||
|
||||
if ((leftIsCap && hasRoundCap))// || (!leftIsCap && hasRoundJoin))
|
||||
{
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texMinX, texMinY)); j++;
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texMinX, texMaxY)); j++;
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texMinX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texMinX, texMaxY));
|
||||
}
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texCenterX, texMinY)); j++;
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texCenterX, texMaxY)); j++;
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texCenterX, texMinY)); j++;
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texCenterX, texMaxY)); j++;
|
||||
if (hasRightRoundCap)
|
||||
else if (leftIsCap && hasSquareCap)
|
||||
{
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texMaxX, texMinY)); j++;
|
||||
texCoords[j] = texture->mapPixel(m2::PointF(texMaxX, texMaxY)); j++;
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMaxY));
|
||||
}
|
||||
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMaxY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMaxY));
|
||||
|
||||
if ((rightIsCap && hasRoundCap) || (!rightIsCap && hasRoundJoin))
|
||||
{
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texMaxX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texMaxX, texMaxY));
|
||||
}
|
||||
else if ((rightIsCap && hasSquareCap) || (!rightIsCap && hasBevelJoin))
|
||||
{
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMinY));
|
||||
texCoords[cur++] = texture->mapPixel(m2::PointF(texCenterX, texMaxY));
|
||||
}
|
||||
|
||||
m2::PointF normal(0, 0);
|
||||
|
||||
addTexturedStripStrided(coords, sizeof(m2::PointF),
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace graphics
|
|||
enum ELineCap
|
||||
{
|
||||
ERoundCap,
|
||||
EButtCap
|
||||
EButtCap,
|
||||
ESquareCap
|
||||
};
|
||||
|
||||
typedef buffer_vector<double, 16> TPattern;
|
||||
|
|
Loading…
Add table
Reference in a new issue