Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
builder.cc
Go to the documentation of this file.
1 
18 #include "ion/text/builder.h"
19 
21 #include "ion/base/datacontainer.h"
22 #include "ion/base/invalid.h"
23 #include "ion/base/logging.h"
24 #include "ion/gfx/indexbuffer.h"
25 #include "ion/gfx/statetable.h"
26 #include "ion/gfx/texture.h"
28 #include "ion/math/range.h"
29 #include "ion/text/layout.h"
30 
31 namespace ion {
32 namespace text {
33 
35 
40 
41 
42 namespace {
43 
46 static const GlyphSet GetGlyphSetFromLayout(
47  const Layout& layout, const base::AllocatorPtr& allocator) {
48  GlyphSet glyph_set(allocator);
49  const size_t num_glyphs = layout.GetGlyphCount();
50  for (size_t i = 0; i < num_glyphs; ++i)
51  glyph_set.insert(layout.GetGlyph(i).glyph_index);
52  return glyph_set;
53 }
54 
57 static const gfx::StateTablePtr BuildStateTable(
58  const base::AllocatorPtr& allocator) {
59  gfx::StateTablePtr state_table(new(allocator) gfx::StateTable());
60  state_table->Enable(gfx::StateTable::kCullFace, false);
61  state_table->Enable(gfx::StateTable::kBlend, true);
62  state_table->SetBlendEquations(gfx::StateTable::kAdd,
64  state_table->SetBlendFunctions(gfx::StateTable::kOne,
68  return state_table;
69 }
70 
76 static const gfx::IndexBufferPtr BuildIndexBuffer(
77  const Layout& layout, gfx::BufferObject::UsageMode usage_mode,
78  const base::AllocatorPtr& allocator) {
79  const base::AllocatorPtr& al =
81 
82  const size_t num_glyphs = layout.GetGlyphCount();
83  base::AllocVector<uint16> indices(
84  al->GetAllocatorForLifetime(base::kShortTerm));
85  indices.reserve(6 * num_glyphs); // 2 triangles per glyph.
86 
87  for (size_t i = 0; i < num_glyphs; ++i) {
88  indices.push_back(static_cast<uint16>(4 * i + 0));
89  indices.push_back(static_cast<uint16>(4 * i + 1));
90  indices.push_back(static_cast<uint16>(4 * i + 2));
91  indices.push_back(static_cast<uint16>(4 * i + 0));
92  indices.push_back(static_cast<uint16>(4 * i + 2));
93  indices.push_back(static_cast<uint16>(4 * i + 3));
94  }
95 
96  gfx::IndexBufferPtr index_buffer(new(al) gfx::IndexBuffer);
97  base::DataContainerPtr container =
98  base::DataContainer::CreateAndCopy<uint16>(
99  &indices[0], indices.size(),
100  usage_mode == gfx::BufferObject::kStaticDraw, al);
101  index_buffer->AddSpec(gfx::BufferObject::kUnsignedShort, 1, 0);
102  index_buffer->SetData(container, sizeof(indices[0]), indices.size(),
103  usage_mode);
104  return index_buffer;
105 }
106 
107 static const gfx::BufferObjectPtr GetBufferObject(
108  const gfx::AttributeArray& attr_array) {
110  if (attr_array.GetBufferAttributeCount() >= 1U) {
111  const gfx::Attribute& attr = attr_array.GetBufferAttribute(0);
113  bo = attr.GetValue<gfx::BufferObjectElement>().buffer_object;
114  }
115  return bo;
116 }
117 
118 static bool CanBufferObjectBeReused(const gfx::BufferObject& bo,
119  size_t num_vertices) {
120  return (bo.GetCount() == num_vertices &&
121  bo.GetData().Get() &&
122  bo.GetUsageMode() != gfx::BufferObject::kStaticDraw &&
123  bo.GetData().Get() &&
124  bo.GetData()->GetData());
125 }
126 
127 
128 } // anonymous namespace
129 
131 
136 
137 
138 Builder::Builder(const FontImagePtr& font_image,
139  const gfxutils::ShaderManagerPtr& shader_manager,
140  const base::AllocatorPtr& allocator)
141  : font_image_(font_image),
142  shader_manager_(shader_manager),
143  allocator_(base::AllocationManager::GetNonNullAllocator(allocator)),
144  image_data_(NULL) {}
145 
147 
148 bool Builder::Build(const Layout& layout,
149  gfx::BufferObject::UsageMode usage_mode) {
151  if (!font_image_.Get() || !layout.GetGlyphCount())
152  return false;
153 
157  DCHECK(!image_data_);
158  const GlyphSet glyph_set = GetGlyphSetFromLayout(
159  layout, allocator_->GetAllocatorForLifetime(base::kShortTerm));
161  font_image_->FindImageData(glyph_set);
162  if (base::IsInvalidReference(image_data))
163  return false;
164  image_data_ = &image_data;
165 
167  if (!node_.Get())
168  node_.Reset(new (allocator_) gfx::Node);
169 
172  if (!node_->GetShaderProgram().Get())
173  node_->SetShaderProgram(BuildShaderProgram());
174  if (!node_->GetStateTable().Get())
175  node_->SetStateTable(BuildStateTable(allocator_));
176 
179  DCHECK(registry_.Get());
180  UpdateUniforms(registry_, node_.Get());
181 
183  if (node_->GetShapes().empty())
184  node_->AddShape(gfx::ShapePtr(new (allocator_) gfx::Shape()));
185  UpdateShape(layout, usage_mode, node_->GetShapes()[0].Get());
186 
187  image_data_ = NULL;
188  return true;
189 }
190 
191 const gfx::ShaderProgramPtr Builder::BuildShaderProgram() {
193  if (!registry_.Get())
194  registry_ = GetShaderInputRegistry();
195  std::string id_string;
196  std::string vertex_source;
197  std::string fragment_source;
198  GetShaderStrings(&id_string, &vertex_source, &fragment_source);
199 
200  gfx::ShaderProgramPtr program;
201  if (shader_manager_.Get()) {
203  program = shader_manager_->CreateShaderProgram(
204  id_string, registry_,
206  new(allocator_) gfxutils::StringComposer(
207  id_string + " vertex shader", vertex_source)),
209  new(allocator_) ion::gfxutils::StringComposer(
210  id_string + " fragment shader", fragment_source)));
211  } else {
213  program = new(allocator_) gfx::ShaderProgram(registry_);
214  program->SetLabel(id_string);
215  program->SetVertexShader(
216  gfx::ShaderPtr(new(allocator_) gfx::Shader(vertex_source)));
217  program->SetFragmentShader(
218  gfx::ShaderPtr(new(allocator_) gfx::Shader(fragment_source)));
219  }
220  return program;
221 }
222 
225  if (font_image_.Get()) {
226  DCHECK(image_data_);
227  texture = image_data_->texture;
228  }
229  return texture;
230 }
231 
233  bool ok = false;
234  if (node && index < node->GetUniforms().size()) {
235  const gfx::Uniform& uniform = node->GetUniforms()[index];
236  if (uniform.IsValid() && uniform.GetType() == gfx::kTextureUniform) {
238  if (uniform.GetValue<gfx::TexturePtr>() != texture)
239  node->SetUniformValue<gfx::TexturePtr>(index, texture);
240  ok = true;
241  }
242  }
243  return ok;
244 }
245 
246 void Builder::StoreGlyphVertices(const Layout& layout, size_t glyph_index,
247  math::Point3f positions[4],
248  math::Point2f texture_coords[4]) {
249  const Layout::Glyph& glyph = layout.GetGlyph(glyph_index);
251 
252  math::Range2f texcoord_rect;
253  DCHECK(image_data_);
254  if (FontImage::GetTextureCoords(*image_data_, glyph.glyph_index,
255  &texcoord_rect)) {
256  for (int i = 0; i < 4; ++i) {
257  positions[i] = glyph.quad.points[i];
258  text_extents_.ExtendByPoint(positions[i]);
259  }
260 
261  const float u_min = texcoord_rect.GetMinPoint()[0];
262  const float u_max = texcoord_rect.GetMaxPoint()[0];
264  const float v_min = texcoord_rect.GetMaxPoint()[1];
265  const float v_max = texcoord_rect.GetMinPoint()[1];
266  texture_coords[0].Set(u_min, v_min);
267  texture_coords[1].Set(u_max, v_min);
268  texture_coords[2].Set(u_max, v_max);
269  texture_coords[3].Set(u_min, v_max);
270  } else {
272  for (int i = 0; i < 4; ++i) {
273  positions[i] = math::Point3f::Zero();
274  texture_coords[i] = math::Point2f::Zero();
275  }
276  }
277 }
278 
279 bool Builder::UpdateAttributeArray(
280  const Layout& layout, gfx::BufferObject::UsageMode usage_mode,
281  const gfx::AttributeArrayPtr& attr_array) {
282  DCHECK(attr_array.Get());
283  const base::AllocatorPtr& allocator = GetAllocator();
284 
286  size_t vertex_size = 0U;
287  size_t num_vertices = 0U;
288  text_extents_.MakeEmpty();
289  base::AllocVector<char> vertex_data =
290  BuildVertexData(layout, &vertex_size, &num_vertices);
291  DCHECK_LT(0U, vertex_size);
292  DCHECK_LT(0U, num_vertices);
293 
296  gfx::BufferObjectPtr bo = GetBufferObject(*attr_array);
297  bool reuse_buffer = false;
298  if (!bo.Get()) {
300  bo = new (allocator) gfx::BufferObject;
301  } else {
304  reuse_buffer = CanBufferObjectBeReused(*bo, num_vertices);
305  }
306 
307  if (reuse_buffer) {
309  base::DataContainer& container = *bo->GetData();
310  char* old_vertex_data = container.GetMutableData<char>();
311  DCHECK(old_vertex_data);
312  memcpy(old_vertex_data, &vertex_data[0], vertex_size * num_vertices);
313  } else {
315  base::DataContainerPtr container =
316  base::DataContainer::CreateAndCopy<char>(
317  &vertex_data[0], vertex_size * num_vertices,
319  bo->SetData(container, vertex_size, num_vertices, usage_mode);
320 
322  if (!attr_array->GetBufferAttributeCount()) {
323  BindAttributes(attr_array, bo);
324  }
325  }
326  return reuse_buffer;
327 }
328 
329 void Builder::UpdateShape(
330  const Layout& layout, gfx::BufferObject::UsageMode usage_mode,
331  gfx::Shape* shape) {
332  shape->SetPrimitiveType(gfx::Shape::kTriangles);
333 
335  if (!shape->GetAttributeArray().Get())
336  shape->SetAttributeArray(
337  gfx::AttributeArrayPtr(new (allocator_) gfx::AttributeArray));
338 
342  const bool buffer_reused =
343  UpdateAttributeArray(layout, usage_mode, shape->GetAttributeArray());
344  if (!shape->GetIndexBuffer().Get() || !buffer_reused) {
345  shape->SetIndexBuffer(BuildIndexBuffer(
346  layout, gfx::BufferObject::kStaticDraw, allocator_));
347  }
348 }
349 
350 } // namespace text
351 } // namespace ion
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
Definition: invalid.h:41
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
Definition: allocator.h:36
gfx::TexturePtr texture
Font glyph texture.
Definition: fontimage.h:74
void StoreGlyphVertices(const Layout &layout, size_t glyph_index, math::Point3f positions[4], math::Point2f texture_coords[4])
Fills in the position and texture_coords for the 4 vertices of the indexed Layout glyph quad...
Definition: builder.cc:246
math::Point3f points[4]
Definition: layout.h:154
virtual void BindAttributes(const gfx::AttributeArrayPtr &attr_array, const gfx::BufferObjectPtr &buffer_object)=0
Binds attributes for the Builder's shader program.
base::AllocatorPtr allocator_
The Allocator for the FreeTypeManager and all its Fonts.
bool UpdateFontImageTextureUniform(size_t index, gfx::Node *node)
Modifies the indexed Texture uniform in the node if necessary to contain the current FontImage image...
Definition: builder.cc:232
std::string text
virtual base::AllocVector< char > BuildVertexData(const Layout &layout, size_t *vertex_size, size_t *num_vertices)=0
Returns a vector of data that represents vertex data, the size of a vertex, the number of vertices...
A ShaderProgram represents an OpenGL shader program that can be applied to shapes.
Definition: shaderprogram.h:38
#define DCHECK(expr)
Definition: logging.h:331
Point2f texture_coords
Definition: shapeutils.cc:74
Simple composer that just returns the string passed to its constructor.
const base::AllocatorPtr & GetAllocator()
Returns the Allocator passed to the constructor.
Definition: builder.h:97
const Glyph & GetGlyph(size_t i) const
Returns the indexed glyph.
Definition: layout.cc:35
A Uniform instance represents a uniform shader argument.
Definition: uniform.h:76
const base::AllocVector< Uniform > & GetUniforms() const
Gets the vector of uniforms.
Definition: uniformholder.h:81
virtual const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Returns the correct Allocator to use to allocate memory with a specific lifetime. ...
Definition: allocator.cc:27
Range< 2, float > Range2f
Definition: range.h:373
base::ReferentPtr< StateTable >::Type StateTablePtr
Convenience typedef for shared pointer to a StateTable.
Definition: statetable.h:705
SharedPtr< Allocator > AllocatorPtr
Definition: allocator.h:51
base::ReferentPtr< IndexBuffer >::Type IndexBufferPtr
Definition: indexbuffer.h:38
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
A BufferObject describes a generic array of data used, for example, to describe the vertices in a Sha...
Definition: bufferobject.h:67
static const AllocatorPtr & GetNonNullAllocator(const AllocatorPtr &allocator)
This convenience function can be used where a non-NULL Allocator pointer is needed.
virtual void GetShaderStrings(std::string *id_string, std::string *vertex_source, std::string *fragment_source)=0
Returns the strings needed for shader definition.
base::AllocSet< GlyphIndex > GlyphSet
Definition: layout.h:47
A Shape object represents a shape (vertices + indices) to draw.
Definition: shape.h:32
static bool GetTextureCoords(const ImageData &image_data, GlyphIndex glyph_index, math::Range2f *rectangle)
Convenience function that sets rectangle to the texture coordinate rectangle to use for the indexed g...
Definition: fontimage.cc:452
bool Build(const Layout &layout, gfx::BufferObject::UsageMode usage_mode)
Builds an Ion Node representing the text string defined by a Layout, using the FontImage passed to th...
Definition: builder.cc:148
size_t GetGlyphCount() const
Returns the number of glyphs added to the layout.
Definition: layout.cc:31
Copyright 2016 Google Inc.
A Layout instance specifies how glyphs are arranged to form text.
Definition: layout.h:127
#define DCHECK_EQ(val1, val2)
Definition: logging.h:332
TexturePtr texture
The Texture to add sub-image data to.
Definition: fontimage.cc:107
base::ReferentPtr< AttributeArray >::Type AttributeArrayPtr
Convenience typedef for shared pointer to a AttributeArray.
void Reset(T *new_shared)
Changes the pointer to point to the given shared, which may be NULL.
Definition: sharedptr.h:92
const T & GetValue() const
If this instance contains a value of type T, this returns a const reference to it.
Definition: shaderinput.h:85
Builder(const FontImagePtr &font_image, const gfxutils::ShaderManagerPtr &shader_manager, const base::AllocatorPtr &allocator)
The constructor is protected because this is an abstract class.
Definition: builder.cc:138
A Shader represents an OpenGL shader stage.
Definition: shader.h:59
bool SetUniformValue(size_t index, const T &value)
Sets the value of the uniform at an index if the index is valid.
Definition: uniformholder.h:86
GlyphIndex glyph_index
Definition: layout.h:173
base::ReferentPtr< DataContainer >::Type DataContainerPtr
Definition: datacontainer.h:38
const gfx::TexturePtr GetFontImageTexture()
Returns a Texture that contains the FontImage image.
Definition: builder.cc:223
base::ReferentPtr< BufferObject >::Type BufferObjectPtr
Convenience typedef for shared pointer to a BufferObject.
Definition: bufferobject.h:31
virtual void UpdateUniforms(const gfx::ShaderInputRegistryPtr &registry, gfx::Node *node)=0
Adds or updates uniforms for the shaders in the node.
bool IsValid() const
Returns true if this is a valid instance created by a ShaderInputRegistry.
Definition: shaderinput.h:59
FontImage::ImageData image_data
The wrapped ImageData instance.
Definition: fontimage.cc:84
A Glyph represents one character glyph in the layout.
Definition: layout.h:160
A Node instance represents a node in a scene graph.
Definition: node.h:45
Data for each image in the FontImage.
Definition: fontimage.h:71
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
~Builder() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
Definition: builder.cc:146
virtual const gfx::ShaderInputRegistryPtr GetShaderInputRegistry()=0
Functions that derived classes must implement.
ValueType GetType() const
Returns the type of the shader input.
Definition: shaderinput.h:80
#define DCHECK_LT(val1, val2)
Definition: logging.h:335
This class can be used in place of std::vector to allow an Ion Allocator to be used for memory alloca...
Definition: allocvector.h:50