forked from organicmaps/organicmaps
review fixes
This commit is contained in:
parent
e6d20c1822
commit
78c3c6bb89
4 changed files with 210 additions and 298 deletions
|
@ -90,37 +90,39 @@ TextLayout::TextLayout(strings::UniString const & string,
|
|||
|
||||
dp::OverlayHandle * LayoutText(const FeatureID & featureID,
|
||||
m2::PointF const & pivot,
|
||||
vector<m2::PointF> const & pixelOffset,
|
||||
vector<TextLayout>::iterator & layoutIter,
|
||||
vector<m2::PointF>::iterator & pixelOffsetIter,
|
||||
float depth,
|
||||
vector<Quad4> & positions,
|
||||
vector<Quad4> & texCoord,
|
||||
vector<Quad4> & fontColor,
|
||||
vector<Quad4> & outlineColor,
|
||||
TextLayout * layouts)
|
||||
vector<glsl_types::Quad4> & positions,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & color,
|
||||
vector<glsl_types::Quad4> & index,
|
||||
dp::RefPointer<dp::TextureSetHolder> textures,
|
||||
int count)
|
||||
{
|
||||
STATIC_ASSERT(sizeof(vec4) == 4 * sizeof(float));
|
||||
STATIC_ASSERT(sizeof(Quad4) == 4 * sizeof(vec4));
|
||||
|
||||
FillColor(fontColor, layouts[0].GetColor());
|
||||
FillColor(outlineColor,layouts[0].GetOutlineColor());
|
||||
FillColor(color, layoutIter->m_font.m_color);
|
||||
FillColor(index,layoutIter->m_font.m_outlineColor);
|
||||
|
||||
int counter = 0;
|
||||
m2::PointD size(0.0, 0.0);
|
||||
m2::PointF offset(numeric_limits<float>::max(), numeric_limits<float>::max());
|
||||
float maxOffset = -numeric_limits<float>::max();
|
||||
for (int j = 0; j < pixelOffset.size(); ++j)
|
||||
float maxOffset = numeric_limits<float>::min();
|
||||
for (int j = 0; j < count; ++j)
|
||||
{
|
||||
float glyphOffset = 0.0;
|
||||
float textRatio = layouts[j].GetTextRatio();
|
||||
float textRatio = layoutIter->m_textSizeRatio;
|
||||
float maxHeight = 0.0f;
|
||||
float minHeight = numeric_limits<float>::max();
|
||||
uint32_t glyphCount = layouts[j].GetGlyphCount();
|
||||
uint32_t glyphCount = layoutIter->GetGlyphCount();
|
||||
double w;
|
||||
for (size_t i = 0; i < glyphCount; ++i)
|
||||
{
|
||||
dp::TextureSetHolder::GlyphRegion const & region = layouts[j].GetGlyphRegion(i);
|
||||
dp::TextureSetHolder::GlyphRegion const & region = layoutIter->m_metrics[i];
|
||||
ASSERT(region.IsValid(), ());
|
||||
layouts[j].GetTextureQuad(region, depth, texCoord[counter]);
|
||||
layoutIter->GetTextureQuad(region, depth, texCoord[counter]);
|
||||
|
||||
float xOffset, yOffset, advance;
|
||||
region.GetMetrics(xOffset, yOffset, advance);
|
||||
|
@ -137,91 +139,29 @@ dp::OverlayHandle * LayoutText(const FeatureID & featureID,
|
|||
minHeight = min(yOffset, minHeight);
|
||||
|
||||
Quad4 & position = positions[counter++];
|
||||
position.v[0] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset) + pixelOffset[j]);
|
||||
position.v[1] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset + h) + pixelOffset[j]);
|
||||
position.v[2] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset) + pixelOffset[j]);
|
||||
position.v[3] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset + h) + pixelOffset[j]);
|
||||
position.v[0] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset) + *pixelOffsetIter);
|
||||
position.v[1] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset + h) + *pixelOffsetIter);
|
||||
position.v[2] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset) + *pixelOffsetIter);
|
||||
position.v[3] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset + h) + *pixelOffsetIter);
|
||||
glyphOffset += advance;
|
||||
}
|
||||
glyphOffset += w / 2.0f;
|
||||
size.x = max(size.x, (double)glyphOffset);
|
||||
offset.x = min(offset.x, pixelOffset[j].x);
|
||||
offset.y = min(offset.y, pixelOffset[j].y + minHeight);
|
||||
maxOffset = max(maxOffset, pixelOffset[j].y + minHeight);
|
||||
offset.x = min(offset.x, pixelOffsetIter->x);
|
||||
offset.y = min(offset.y, pixelOffsetIter->y + minHeight);
|
||||
maxOffset = max(maxOffset, pixelOffsetIter->y + minHeight);
|
||||
size.y = max(size.y, (double)maxHeight);
|
||||
++layoutIter;
|
||||
++pixelOffsetIter;
|
||||
}
|
||||
size.y += maxOffset - offset.y;
|
||||
return new StraightTextHandle(featureID, pivot, size, offset, depth);
|
||||
}
|
||||
|
||||
|
||||
dp::OverlayHandle * TextLayout::LayoutText(const FeatureID & featureID,
|
||||
m2::PointF const & pivot,
|
||||
m2::PointF const & pixelOffset,
|
||||
float depth,
|
||||
vector<Quad4> & positions,
|
||||
vector<Quad4> & texCoord,
|
||||
vector<Quad4> & fontColor,
|
||||
vector<Quad4> & outlineColor) const
|
||||
{
|
||||
STATIC_ASSERT(sizeof(vec4) == 4 * sizeof(float));
|
||||
STATIC_ASSERT(sizeof(Quad4) == 4 * sizeof(vec4));
|
||||
|
||||
size_t glyphCount = GetGlyphCount();
|
||||
ASSERT(glyphCount <= positions.size(), ());
|
||||
ASSERT(glyphCount <= texCoord.size(), ());
|
||||
ASSERT(glyphCount <= fontColor.size(), ());
|
||||
ASSERT(glyphCount <= outlineColor.size(), ());
|
||||
|
||||
FillColor(fontColor, m_font.m_color);
|
||||
FillColor(outlineColor, m_font.m_outlineColor);
|
||||
|
||||
float maxHeight = 0.0f;
|
||||
float minHeight = numeric_limits<float>::max();
|
||||
|
||||
float glyphOffset = 0.0;
|
||||
for (size_t i = 0; i < glyphCount; ++i)
|
||||
{
|
||||
GlyphRegion const & region = m_metrics[i];
|
||||
ASSERT(region.IsValid(), ());
|
||||
GetTextureQuad(region, depth, texCoord[i]);
|
||||
|
||||
float xOffset, yOffset, advance;
|
||||
region.GetMetrics(xOffset, yOffset, advance);
|
||||
|
||||
xOffset *= m_textSizeRatio;
|
||||
yOffset *= m_textSizeRatio;
|
||||
advance *= m_textSizeRatio;
|
||||
|
||||
m2::PointU size;
|
||||
region.GetPixelSize(size);
|
||||
double const h = size.y * m_textSizeRatio;
|
||||
double const w = size.x * m_textSizeRatio;
|
||||
maxHeight = max((float)h, maxHeight);
|
||||
minHeight = min(yOffset, minHeight);
|
||||
|
||||
Quad4 & position = positions[i];
|
||||
position.v[0] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset) + pixelOffset);
|
||||
position.v[1] = vec4(pivot, m2::PointF(glyphOffset + xOffset, yOffset + h) + pixelOffset);
|
||||
position.v[2] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset) + pixelOffset);
|
||||
position.v[3] = vec4(pivot, m2::PointF(glyphOffset + w + xOffset, yOffset + h) + pixelOffset);
|
||||
glyphOffset += advance;
|
||||
}
|
||||
|
||||
GlyphRegion const & region = m_metrics[0];
|
||||
m2::PointU size;
|
||||
region.GetPixelSize(size);
|
||||
double const w = size.x * m_textSizeRatio;
|
||||
glyphOffset += w / 2.0f;
|
||||
|
||||
return new StraightTextHandle(featureID, pivot, m2::PointD(glyphOffset, maxHeight),
|
||||
m2::PointF(pixelOffset.x, pixelOffset.y + minHeight), depth);
|
||||
}
|
||||
|
||||
void TextLayout::InitPathText(float depth,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & fontColor,
|
||||
vector<glsl_types::Quad4> & outlineColor) const
|
||||
vector<glsl_types::Quad4> & index) const
|
||||
{
|
||||
STATIC_ASSERT(sizeof(vec4) == 4 * sizeof(float));
|
||||
STATIC_ASSERT(sizeof(Quad4) == 4 * sizeof(vec4));
|
||||
|
@ -229,10 +169,10 @@ void TextLayout::InitPathText(float depth,
|
|||
size_t glyphCount = GetGlyphCount();
|
||||
ASSERT(glyphCount <= texCoord.size(), ());
|
||||
ASSERT(glyphCount <= fontColor.size(), ());
|
||||
ASSERT(glyphCount <= outlineColor.size(), ());
|
||||
ASSERT(glyphCount <= index.size(), ());
|
||||
|
||||
FillColor(fontColor, m_font.m_color);
|
||||
FillColor(outlineColor, m_font.m_outlineColor);
|
||||
FillColor(index, m_font.m_outlineColor);
|
||||
|
||||
for (size_t i = 0; i < glyphCount; ++i)
|
||||
GetTextureQuad(m_metrics[i], depth, texCoord[i]);
|
||||
|
@ -315,26 +255,6 @@ float TextLayout::GetPixelHeight() const
|
|||
return m_font.m_size;
|
||||
}
|
||||
|
||||
dp::Color TextLayout::GetColor() const
|
||||
{
|
||||
return m_font.m_color;
|
||||
}
|
||||
|
||||
dp::Color TextLayout::GetOutlineColor() const
|
||||
{
|
||||
return m_font.m_outlineColor;
|
||||
}
|
||||
|
||||
dp::TextureSetHolder::GlyphRegion & TextLayout::GetGlyphRegion(int index)
|
||||
{
|
||||
return m_metrics[index];
|
||||
}
|
||||
|
||||
float TextLayout::GetTextRatio() const
|
||||
{
|
||||
return m_textSizeRatio;
|
||||
}
|
||||
|
||||
void TextLayout::GetTextureQuad(GlyphRegion const & region,
|
||||
float depth,
|
||||
Quad4 & quad) const
|
||||
|
|
|
@ -27,15 +27,6 @@ public:
|
|||
df::FontDecl const & font,
|
||||
dp::RefPointer<dp::TextureSetHolder> textures);
|
||||
|
||||
dp::OverlayHandle * LayoutText(FeatureID const & featureID,
|
||||
m2::PointF const & pivot,
|
||||
m2::PointF const & pixelOffset,
|
||||
float depth,
|
||||
vector<glsl_types::Quad4> & positions,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & fontColor,
|
||||
vector<glsl_types::Quad4> & outlineColor) const;
|
||||
|
||||
void InitPathText(float depth,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & fontColor,
|
||||
|
@ -51,35 +42,31 @@ public:
|
|||
uint32_t GetTextureSet() const;
|
||||
float GetPixelLength() const;
|
||||
float GetPixelHeight() const;
|
||||
float GetTextRatio() const;
|
||||
dp::Color GetColor() const;
|
||||
dp::Color GetOutlineColor() const;
|
||||
GlyphRegion & GetGlyphRegion(int index);
|
||||
|
||||
private:
|
||||
float AccumulateAdvance(double const & currentValue, GlyphRegion const & reg2) const;
|
||||
void InitMetric(strings::UniChar const & unicodePoint, dp::RefPointer<dp::TextureSetHolder> textures);
|
||||
|
||||
public:
|
||||
void GetTextureQuad(GlyphRegion const & region, float depth, glsl_types::Quad4 & quad) const;
|
||||
void GetMetrics(int32_t const index, float & xOffset, float & yOffset, float & advance,
|
||||
float & halfWidth, float & halfHeight) const;
|
||||
void GetTextureQuad(GlyphRegion const & region, float depth, glsl_types::Quad4 & quad) const;
|
||||
|
||||
private:
|
||||
buffer_vector<GlyphRegion, 32> m_metrics;
|
||||
df::FontDecl m_font;
|
||||
float m_textSizeRatio;
|
||||
};
|
||||
|
||||
dp::OverlayHandle * LayoutText(const FeatureID & featureID,
|
||||
m2::PointF const & pivot,
|
||||
vector<m2::PointF> const & pixelOffset,
|
||||
float depth,
|
||||
vector<glsl_types::Quad4> & positions,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & fontColor,
|
||||
vector<glsl_types::Quad4> & outlineColor,
|
||||
TextLayout * layouts);
|
||||
friend dp::OverlayHandle * LayoutText(const FeatureID & featureID,
|
||||
m2::PointF const & pivot,
|
||||
vector<TextLayout>::iterator & layoutIter,
|
||||
vector<m2::PointF>::iterator & pixelOffsetIter,
|
||||
float depth,
|
||||
vector<glsl_types::Quad4> & positions,
|
||||
vector<glsl_types::Quad4> & texCoord,
|
||||
vector<glsl_types::Quad4> & color,
|
||||
vector<glsl_types::Quad4> & index,
|
||||
dp::RefPointer<dp::TextureSetHolder> textures,
|
||||
int count);
|
||||
};
|
||||
|
||||
class SharedTextLayout
|
||||
{
|
||||
|
|
|
@ -26,98 +26,92 @@ using m2::PointF;
|
|||
|
||||
namespace
|
||||
{
|
||||
float const TEXT_EXPAND_FACTOR = 1.3f;
|
||||
float const TEXT_EXPAND_FACTOR = 1.3f;
|
||||
|
||||
PointF GetShift(dp::Anchor anchor, float width, float height)
|
||||
{
|
||||
switch(anchor)
|
||||
{
|
||||
case dp::Center: return PointF(-width / 2.0f, height / 2.0f);
|
||||
case dp::Left: return PointF(0.0f, height / 2.0f);
|
||||
case dp::Right: return PointF(-width, height / 2.0f);
|
||||
case dp::Top: return PointF(-width / 2.0f, height);
|
||||
case dp::Bottom: return PointF(-width / 2.0f, 0);
|
||||
case dp::LeftTop: return PointF(0.0f, height);
|
||||
case dp::RightTop: return PointF(-width, height);
|
||||
case dp::LeftBottom: return PointF(0.0f, 0.0f);
|
||||
case dp::RightBottom: return PointF(-width, 0.0f);
|
||||
default: return PointF(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchText(dp::RefPointer<dp::Batcher> batcher, int32_t textureSet,
|
||||
vector<glsl_types::Quad4> const & positions,
|
||||
vector<glsl_types::Quad4> const & texCoord,
|
||||
vector<glsl_types::Quad4> const & fontColors,
|
||||
vector<glsl_types::Quad4> const & outlineColor,
|
||||
size_t glyphCount,
|
||||
dp::OverlayHandle * handle)
|
||||
{
|
||||
ASSERT(glyphCount <= positions.size(), ());
|
||||
ASSERT(positions.size() == texCoord.size(), ());
|
||||
ASSERT(positions.size() == fontColors.size(), ());
|
||||
ASSERT(positions.size() == outlineColor.size(), ());
|
||||
|
||||
dp::GLState state(gpu::FONT_PROGRAM, dp::GLState::OverlayLayer);
|
||||
state.SetTextureSet(textureSet);
|
||||
state.SetBlending(dp::Blending(true));
|
||||
|
||||
dp::AttributeProvider provider(4, 4 * glyphCount);
|
||||
{
|
||||
dp::BindingInfo position(1);
|
||||
dp::BindingDecl & decl = position.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_position";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(0, position, dp::MakeStackRefPointer((void*)&positions[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo texcoord(1);
|
||||
dp::BindingDecl & decl = texcoord.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_texcoord";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(1, texcoord, dp::MakeStackRefPointer((void*)&texCoord[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo base_color(1);
|
||||
dp::BindingDecl & decl = base_color.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_color";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(2, base_color, dp::MakeStackRefPointer((void*)&fontColors[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo outline_color(1);
|
||||
dp::BindingDecl & decl = outline_color.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_outline_color";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(3, outline_color, dp::MakeStackRefPointer((void*)&outlineColor[0]));
|
||||
}
|
||||
|
||||
batcher->InsertListOfStrip(state, dp::MakeStackRefPointer(&provider), MovePointer(handle), 4);
|
||||
}
|
||||
}
|
||||
|
||||
TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params)
|
||||
: m_basePoint(basePoint),
|
||||
m_params(params)
|
||||
PointF GetShift(dp::Anchor anchor, float width, float height)
|
||||
{
|
||||
switch(anchor)
|
||||
{
|
||||
case dp::Center: return PointF(-width / 2.0f, height / 2.0f);
|
||||
case dp::Left: return PointF(0.0f, height / 2.0f);
|
||||
case dp::Right: return PointF(-width, height / 2.0f);
|
||||
case dp::Top: return PointF(-width / 2.0f, height);
|
||||
case dp::Bottom: return PointF(-width / 2.0f, 0);
|
||||
case dp::LeftTop: return PointF(0.0f, height);
|
||||
case dp::RightTop: return PointF(-width, height);
|
||||
case dp::LeftBottom: return PointF(0.0f, 0.0f);
|
||||
case dp::RightBottom: return PointF(-width, 0.0f);
|
||||
default: return PointF(0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchText(dp::RefPointer<dp::Batcher> batcher, int32_t textureSet,
|
||||
vector<glsl_types::Quad4> const & positions,
|
||||
vector<glsl_types::Quad4> const & texCoord,
|
||||
vector<glsl_types::Quad4> const & fontColors,
|
||||
vector<glsl_types::Quad4> const & outlineColor,
|
||||
size_t glyphCount,
|
||||
dp::OverlayHandle * handle)
|
||||
{
|
||||
ASSERT(glyphCount <= positions.size(), ());
|
||||
ASSERT(positions.size() == texCoord.size(), ());
|
||||
ASSERT(positions.size() == fontColors.size(), ());
|
||||
ASSERT(positions.size() == outlineColor.size(), ());
|
||||
|
||||
dp::GLState state(gpu::FONT_PROGRAM, dp::GLState::OverlayLayer);
|
||||
state.SetTextureSet(textureSet);
|
||||
state.SetBlending(dp::Blending(true));
|
||||
|
||||
dp::AttributeProvider provider(4, 4 * glyphCount);
|
||||
{
|
||||
dp::BindingInfo position(1);
|
||||
dp::BindingDecl & decl = position.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_position";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(0, position, dp::MakeStackRefPointer((void*)&positions[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo texcoord(1);
|
||||
dp::BindingDecl & decl = texcoord.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_texcoord";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(1, texcoord, dp::MakeStackRefPointer((void*)&texCoord[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo base_color(1);
|
||||
dp::BindingDecl & decl = base_color.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_color";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(2, base_color, dp::MakeStackRefPointer((void*)&fontColors[0]));
|
||||
}
|
||||
{
|
||||
dp::BindingInfo outline_color(1);
|
||||
dp::BindingDecl & decl = outline_color.GetBindingDecl(0);
|
||||
decl.m_attributeName = "a_outline_color";
|
||||
decl.m_componentCount = 4;
|
||||
decl.m_componentType = gl_const::GLFloatType;
|
||||
decl.m_offset = 0;
|
||||
decl.m_stride = 0;
|
||||
provider.InitStream(3, outline_color, dp::MakeStackRefPointer((void*)&outlineColor[0]));
|
||||
}
|
||||
|
||||
batcher->InsertListOfStrip(state, dp::MakeStackRefPointer(&provider), MovePointer(handle), 4);
|
||||
}
|
||||
|
||||
///Old code
|
||||
void TextShape::visSplit(strings::UniString const & visText,
|
||||
buffer_vector<strings::UniString, 3> & res,
|
||||
char const * delims,
|
||||
bool splitAllFound) const
|
||||
void SplitText(strings::UniString const & visText,
|
||||
buffer_vector<strings::UniString, 3> & res,
|
||||
char const * delims,
|
||||
bool splitAllFound)
|
||||
{
|
||||
if (!splitAllFound)
|
||||
{
|
||||
|
@ -125,19 +119,19 @@ void TextShape::visSplit(strings::UniString const & visText,
|
|||
if (count > 15)
|
||||
{
|
||||
// split on two parts
|
||||
typedef strings::UniString::const_iterator IterT;
|
||||
IterT const iMiddle = visText.begin() + count/2;
|
||||
typedef strings::UniString::const_iterator TIter;
|
||||
TIter const iMiddle = visText.begin() + count/2;
|
||||
|
||||
size_t const delimsSize = strlen(delims);
|
||||
|
||||
// find next delimeter after middle [m, e)
|
||||
IterT iNext = find_first_of(iMiddle,
|
||||
TIter iNext = find_first_of(iMiddle,
|
||||
visText.end(),
|
||||
delims, delims + delimsSize);
|
||||
|
||||
// find last delimeter before middle [b, m)
|
||||
IterT iPrev = find_first_of(reverse_iterator<IterT>(iMiddle),
|
||||
reverse_iterator<IterT>(visText.begin()),
|
||||
TIter iPrev = find_first_of(reverse_iterator<TIter>(iMiddle),
|
||||
reverse_iterator<TIter>(visText.begin()),
|
||||
delims, delims + delimsSize).base();
|
||||
// don't do split like this:
|
||||
// xxxx
|
||||
|
@ -172,78 +166,77 @@ void TextShape::visSplit(strings::UniString const & visText,
|
|||
else
|
||||
{
|
||||
// split string using according to all delimiters
|
||||
typedef strings::SimpleDelimiter DelimT;
|
||||
for (strings::TokenizeIterator<DelimT> iter(visText, DelimT(delims)); iter; ++iter)
|
||||
typedef strings::SimpleDelimiter TDelim;
|
||||
for (strings::TokenizeIterator<TDelim> iter(visText, TDelim(delims)); iter; ++iter)
|
||||
res.push_back(iter.GetUniString());
|
||||
}
|
||||
}
|
||||
|
||||
pair<bool, bool> GetBidiTexts(
|
||||
strings::UniString const & visText, strings::UniString const & auxVisText,
|
||||
strings::UniString & primaryText, strings::UniString & secondaryText)
|
||||
{
|
||||
primaryText = fribidi::log2vis(visText);
|
||||
secondaryText = fribidi::log2vis(auxVisText);
|
||||
return make_pair(visText != primaryText, auxVisText != secondaryText);
|
||||
}
|
||||
|
||||
void GetLayouts(vector<TextLayout> & layouts, strings::UniString const & text, bool isBidi, FontDecl const & fontDecl, dp::RefPointer<dp::TextureSetHolder> textures)
|
||||
{
|
||||
if (!isBidi)
|
||||
{
|
||||
buffer_vector<strings::UniString, 3> res;
|
||||
SplitText(text, res, " \n\t", false);
|
||||
for (int i = 0; i < res.size(); ++i)
|
||||
{
|
||||
TextLayout tl = TextLayout(res[res.size() - i - 1], fontDecl, textures);
|
||||
if (tl.GetGlyphCount() == 0)
|
||||
continue;
|
||||
layouts.push_back(tl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TextLayout tl = TextLayout(text, fontDecl, textures);
|
||||
if (tl.GetGlyphCount() == 0)
|
||||
return;
|
||||
layouts.push_back(tl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params)
|
||||
: m_basePoint(basePoint),
|
||||
m_params(params)
|
||||
{
|
||||
}
|
||||
|
||||
void TextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const
|
||||
{
|
||||
ASSERT(!m_params.m_primaryText.empty(), ());
|
||||
vector<TextLayout> layouts;
|
||||
strings::UniString primaryText, secondaryText;
|
||||
pair<bool, bool> isBidi = GetBidiTexts(strings::MakeUniString(m_params.m_primaryText), strings::MakeUniString(m_params.m_secondaryText), primaryText, secondaryText);
|
||||
if (m_params.m_secondaryText.empty())
|
||||
{
|
||||
strings::UniString text = fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText));
|
||||
if (text.size() == 0)
|
||||
GetLayouts(layouts, primaryText, isBidi.first, m_params.m_primaryTextFont, textures);
|
||||
if (layouts.size() == 0)
|
||||
return;
|
||||
|
||||
buffer_vector<strings::UniString, 3> res;
|
||||
visSplit(text, res, " \n\t", false);
|
||||
for (int i = 0; i < res.size(); ++i)
|
||||
layouts.push_back(TextLayout(res[res.size() - i - 1], m_params.m_primaryTextFont, textures));
|
||||
|
||||
vector<bool> dels(layouts.size(), false);
|
||||
dels[dels.size() - 1] = true;
|
||||
DrawPolyLine(batcher, layouts, dels);
|
||||
DrawMultipleLines(batcher, layouts, -1, textures);
|
||||
}
|
||||
else
|
||||
{
|
||||
strings::UniString primaryText = fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText));
|
||||
strings::UniString secondaryText = fribidi::log2vis(strings::MakeUniString(m_params.m_secondaryText));
|
||||
uint32_t primGlyphCount = primaryText.size();
|
||||
uint32_t secondGlyphCount = secondaryText.size();
|
||||
buffer_vector<strings::UniString, 3> primRes;
|
||||
buffer_vector<strings::UniString, 3> secRes;
|
||||
|
||||
if (primGlyphCount == 0 && secondGlyphCount == 0)
|
||||
GetLayouts(layouts, secondaryText, isBidi.second, m_params.m_secondaryTextFont, textures);
|
||||
int size = layouts.size() - 1;
|
||||
GetLayouts(layouts, primaryText, isBidi.first, m_params.m_primaryTextFont, textures);
|
||||
if (layouts.size() == 0)
|
||||
return;
|
||||
|
||||
if (primGlyphCount == 0)
|
||||
{
|
||||
visSplit(secondaryText, secRes, " \n\t", false);
|
||||
for (int i = 0; i < secRes.size(); ++i)
|
||||
layouts.push_back(TextLayout(secRes[secRes.size() - i - 1], m_params.m_secondaryTextFont, textures));
|
||||
vector<bool> dels(layouts.size(), false);
|
||||
dels[dels.size() - 1] = true;
|
||||
DrawPolyLine(batcher, layouts, dels);
|
||||
}
|
||||
else if (secondGlyphCount == 0)
|
||||
{
|
||||
visSplit(primaryText, primRes, " \n\t", false);
|
||||
for (int i = 0; i < primRes.size(); ++i)
|
||||
layouts.push_back(TextLayout(primRes[primRes.size() - i - 1], m_params.m_primaryTextFont, textures));
|
||||
vector<bool> dels(layouts.size(), false);
|
||||
dels[dels.size() - 1] = true;
|
||||
DrawPolyLine(batcher, layouts, dels);
|
||||
}
|
||||
else
|
||||
{
|
||||
visSplit(primaryText, primRes, " \n\t", false);
|
||||
visSplit(secondaryText, secRes, " \n\t", false);
|
||||
for (int i = 0; i < secRes.size(); ++i)
|
||||
layouts.push_back(TextLayout(secRes[secRes.size() - i - 1], m_params.m_secondaryTextFont, textures));
|
||||
for (int i = 0; i < primRes.size(); ++i)
|
||||
layouts.push_back(TextLayout(primRes[primRes.size() - i - 1], m_params.m_primaryTextFont, textures));
|
||||
vector<bool> dels(layouts.size(), false);
|
||||
dels[secRes.size()-1] = true;
|
||||
dels[dels.size() - 1] = true;
|
||||
DrawPolyLine(batcher, layouts, dels);
|
||||
}
|
||||
DrawMultipleLines(batcher, layouts, size, textures);
|
||||
}
|
||||
}
|
||||
|
||||
void TextShape::DrawPolyLine(dp::RefPointer<dp::Batcher> batcher, vector<TextLayout> & layouts, vector<bool> & delims) const
|
||||
void TextShape::DrawMultipleLines(dp::RefPointer<dp::Batcher> batcher, vector<TextLayout> & layouts,
|
||||
int delim, dp::RefPointer<dp::TextureSetHolder> textures) const
|
||||
{
|
||||
uint32_t const count = layouts.size();
|
||||
vector<float> lengths(count);
|
||||
|
@ -267,35 +260,49 @@ void TextShape::DrawPolyLine(dp::RefPointer<dp::Batcher> batcher, vector<TextLay
|
|||
vector<glsl_types::Quad4> positions(symCount);
|
||||
vector<glsl_types::Quad4> texCoord(symCount);
|
||||
vector<glsl_types::Quad4> fontColor(symCount);
|
||||
vector<glsl_types::Quad4> outlineColor(symCount);
|
||||
vector<glsl_types::Quad4> indexes(symCount);
|
||||
|
||||
float dy = (1.0f - TEXT_EXPAND_FACTOR) * heights[0];
|
||||
vector<PointF> pixelOffset;
|
||||
vector<PointF> pixelOffset(count);
|
||||
uint32_t delSymCount = 0;
|
||||
uint32_t lastIndex = 0;
|
||||
ASSERT(delims.back(), ());
|
||||
vector<TextLayout>::iterator it1;
|
||||
vector<PointF>::iterator it2;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
float const dx = (maxLength - lengths[i]) / 2.0f;
|
||||
pixelOffset.push_back(PointF(dx, dy) + anchorOffset + m_params.m_primaryOffset);
|
||||
pixelOffset[i] = PointF(dx, dy) + anchorOffset + m_params.m_primaryOffset;
|
||||
dy -= heights[i] * TEXT_EXPAND_FACTOR;
|
||||
delSymCount += layouts[i].GetGlyphCount();
|
||||
if (delims[i])
|
||||
if (i == delim)
|
||||
{
|
||||
it2 = pixelOffset.begin();
|
||||
it1 = layouts.begin();
|
||||
dp::OverlayHandle * handle = LayoutText(m_params.m_featureID, m_basePoint,
|
||||
pixelOffset, m_params.m_depth,
|
||||
positions, texCoord, fontColor, outlineColor, &layouts[lastIndex]);
|
||||
it1, it2, m_params.m_depth,
|
||||
positions, texCoord, fontColor,
|
||||
indexes, textures, i + 1);
|
||||
|
||||
BatchText(batcher, layouts[0].GetTextureSet(),
|
||||
positions, texCoord,
|
||||
fontColor, outlineColor,
|
||||
delSymCount, handle);
|
||||
positions, texCoord,
|
||||
fontColor, indexes,
|
||||
delSymCount, handle);
|
||||
|
||||
pixelOffset.clear();
|
||||
delSymCount = 0;
|
||||
lastIndex = i + 1;
|
||||
}
|
||||
}
|
||||
it2 = pixelOffset.begin() + lastIndex;
|
||||
it1 = layouts.begin() + lastIndex;
|
||||
dp::OverlayHandle * handle = LayoutText(m_params.m_featureID, m_basePoint,
|
||||
it1, it2, m_params.m_depth,
|
||||
positions, texCoord, fontColor, indexes,
|
||||
textures, count - lastIndex);
|
||||
|
||||
BatchText(batcher, layouts[0].GetTextureSet(),
|
||||
positions, texCoord,
|
||||
fontColor, indexes,
|
||||
delSymCount, handle);
|
||||
}
|
||||
|
||||
} //end of df namespace
|
||||
|
|
|
@ -17,13 +17,11 @@ public:
|
|||
TextShape(m2::PointF const & basePoint, TextViewParams const & params);
|
||||
|
||||
void Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const;
|
||||
void visSplit(strings::UniString const & visText,
|
||||
buffer_vector<strings::UniString, 3> & res,
|
||||
char const * delims,
|
||||
bool splitAllFound) const;
|
||||
private:
|
||||
void DrawPolyLine(dp::RefPointer<dp::Batcher> batcher, vector<TextLayout> & layouts, vector<bool> & delims) const;
|
||||
|
||||
void DrawMultipleLines(dp::RefPointer<dp::Batcher> batcher,
|
||||
vector<TextLayout> & layouts,
|
||||
int delim,
|
||||
dp::RefPointer<dp::TextureSetHolder> textures) const;
|
||||
private:
|
||||
m2::PointF m_basePoint;
|
||||
TextViewParams m_params;
|
||||
|
|
Loading…
Add table
Reference in a new issue