====
Text
====

Like all other geometry, each text object is represented in the database by a key. |HPSNOW| has many different text attributes that are accessed through the key. Unlike other geometry, text attributes can be set at either the object or segment level. If any text attribute is set at both the segment level and on the ``TextKey``, the ``TextKey`` setting takes precedence. Text is configured by a ``HPS::TextKit`` and inserted using ``HPS::SegmentKey::InsertText``:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7.cpp
		   :start-after: //! [0207_a]
		   :end-before: //! [0207_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7.cs
		   :start-after: //! [0207_a]
		   :end-before: //! [0207_a]

.. image:: images/40.png

*Text inserted at 40 pixels high*

There is no limit to the length of text in a text object. In our C++ APIs, all string input is assumed to be UTF-8 encoded (for C#, simply use the ``String`` class). The ``UTF8`` class can take any wide-character string and UTF-8 encode it. You can pass a ``UTF8`` object to any function expecting a ``char const *``. For most Western European languages, the ASCII character set matches the UTF-8 code points, so there is typically no need to encode these strings. To construct a ``UTF8`` object, simply pass a character string to the constructor:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7.cpp
		   :start-after: //! [0207_b]
		   :end-before: //! [0207_b]
		   
	.. group-tab:: C#

		UTF8 does not apply to C#. Simply use the 'String' object in its place.
		   

Finding Fonts
-------------

The font directory is where |HPSNOW| looks for installed fonts. On Windows platforms, this doesn't need to be adjusted unless your fonts are installed in a non-standard location. However, if necessary, this value can be set using ``HPS::World.SetFontDirectory(<font_path>)``. A list of directories can be specified using a semicolon-separated list.

You can also choose from a list of fonts that are available on the system. To do this from |HPSNOW|, you must perform a font search. Font searching is done using a ``HPS::WindowKey``:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_font_search.cpp
		   :start-after: //! [font_search]
		   :end-before: //! [font_search]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_font_search.cs
		   :start-after: //! [font_search]
		   :end-before: //! [font_search]

If no font is explicitly set, |HPSNOW| will use the default font, which is named "stroked". The font is programmatically rendered and thus there is no external font file. An example of that font can be found :doc:`in the appendix <appendix_stroked_font>`. The "ts3d" font, also included with |HPSNOW|, additionally offers :ref:`GD&T <prog_guide/0203_text:Using GD&T symbols>`.


Setting Text Size
=================

Frequently, it is desirable for text size to adjust to different orientations or zoom levels, or to remain a fixed size while a scene is zoomed. Text size can be specified in several different units using ``HPS::TextKey::SetSize`` or ``HPS::TextAttributeControl::SetSize``.

.. csv-table::
	:header: "Enumeration", "Description"
	
	"HPS::Text::SizeUnits::ObjectSpace", ":raw-html:`The number indicates text size in object space.<br>This allows for fully transformable text, which is<br>sized the same as most of the other geometries.`"	
	"HPS::Text::SizeUnits::WorldSpace", ":raw-html:`This number indicates the text size in world space.<br>This is very similar to ObjectSpace except it includes<br> any scales from any modelling matrices applied to the containing segment.`"
	"HPS::Text::SizeUnits::WindowRelative", "Text is sized relative to the size of the subwindow it inhabits."
	"HPS::Text::SizeUnits::SubscreenRelative", "Text is sized relative to the size of the outer window."
	"HPS::Text::SizeUnits::Pixels", "Text is sized in absolute pixels."
	"HPS::Text::SizeUnits::Points", "Text is sized in points (see following notes about points)"


Notes on Specifying Text in Points
----------------------------------

A point (not to be confused with a coordinate point) is a common text measurement approximately equal to 1/72 inch. When the text size is specified in points, the text will stay the same size, regardless of the size of the output window, and also regardless of the resolution of the display.

If your output display has a resolution of 72 pixels per inch, then a pixel is the same size as a point. If you have a 13-inch display, 72 pixels per inch corresponds roughly to a resolution of 640x480; on a 21-inch display, it corresponds roughly to a resolution of 1024x780.

It is important to note that text specified in points can appear to be different sizes on different monitors. To render point-sized fonts in a scene, |HPSNOW| relies on the accuracy of the properties reported by machine-specific display hardware. As this can be inconsistent across a wide variety of machines, the rendered text size may vary across different hardware configurations. If you want consistent sizing across different display hardware, we recommend that you specify ``Pixels``, ``SubscreenRelative``, or ``WindowRelative`` font sizes.

Finally, if your output window contains |HPSNOW| :doc:`subwindows <0304_subwindows>`, then it may be convenient to use ``HPS::TextKey::SetSize()`` to set the text size in window relative units (``HPS::Text::SizeUnits::WindowRelative``).


Multi-Line Text
===============

Multi-line text is available by simply inserting a line break within the text string. The space between the lines can be controlled using ``HPS::TextKey::SetLineSpacing`` or ``HPS::TextAttributeControl::SetLineSpacing``. The parameter you specify is simply a multiple of the default line spacing.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_2_a.cpp
		   :start-after: //! [020702_a]
		   :end-before: //! [020702_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_2_a.cs
		   :start-after: //! [020702_a]
		   :end-before: //! [020702_a]


Manipulating Text
=================

Like other geometry, text can be manipulated after insertion using the ``HPS::TextKey``. Position, font, size, and color, among other attributes are available for modification. The text content itself can be accessed via ``HPS::TextKey::ShowText`` and can be modified using the various ``Edit`` functions. When editing text, the content is accessed and specified by row and column position.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_3_a.cpp
		   :start-after: //! [020703_a]
		   :end-before: //! [020703_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_3_a.cs
		   :start-after: //! [020703_a]
		   :end-before: //! [020703_a]

.. image:: images/editing_text.png

*The original (left) and edited text (right)*

Note that the row and column counts used as the parameters are offsets, hence the first column would be column zero. ``HPS::TextKey::EditTextByReplacement`` can also be used but it is a 1-to-1 operation and is therefore only useful if you're replacing a substring with string of equal length.


Computing Text Extent
---------------------

Often, it is necessary to know in advance what size text is going to be drawn on the screen so that it can be positioned accurately within the scene, or so geometry can be properly drawn around the text. |HPSNOW| can compute text extents for you based on the font and window characteristics. Because the calculation relies on many top-level parameters (such as screen resolution), you need to use a ``HPS::KeyPath`` object, which builds a segment hierarchy from the text object to the top-level window. Information on using a key path can be found in :ref:`this section <prog_guide/0102_api_conventions:Using keys and objects>`.

The size of the text extents are returned as a fraction of the text's parent window (or subwindow).

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_extents.cpp
		   :start-after: //! [text_extents]
		   :end-before: //! [text_extents]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_extents.cs
		   :start-after: //! [text_extents]
		   :end-before: //! [text_extents]


Setting a Text Region
---------------------

Computing the text extents returns the screen size of text, but it is sometimes desirable to do the opposite: to specify a screen-space extent that you want the text to be drawn within. This is useful when text needs to fit into a predefined area. In |HPSNOW|, this box is called a *text region*. Text regions are linear in shape, but text path, alignment, and rotation values will continue to be honored. For example, if you wanted to draw text between the points [-1, 0, 0] and [1, 0, 0], you could do something like this:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7.cpp
		   :start-after: //! [text_region]
		   :end-before: //! [text_region]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7.cs
		   :start-after: //! [text_region]
		   :end-before: //! [text_region]

.. image:: images/text_region.png

*In this example, the text is formatted to fit between the two points, marked by red dots.*

To unset a text region, call the above method with zero points in the region argument.


Enabling Text Transformations
=============================

When text is part of a scene, it is often necessary for the text to remain unaffected by the camera orientation so that text is always billboarded in the view. This billboarding effect is the |HPSNOW| default. To force text to obey modelling transformations, simply enable text transforms in the following way:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_4_ab.cpp
		   :start-after: //! [020704_a]
		   :end-before: //! [020704_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_4_ab.cs
		   :start-after: //! [020704_a]
		   :end-before: //! [020704_a]
		   
|HPSNOW| also provides two other types of text transforms that relate to individual characters within a text string. ``CharacterPositionOnly`` will enable transforms on the text's path but the orientation of individual characters remains unaffected. 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_4_ab.cpp
		   :start-after: //! [020704_b]
		   :end-before: //! [020704_b]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_4_ab.cs
		   :start-after: //! [020704_b]
		   :end-before: //! [020704_b]
		   

Alignment and Justification
===========================

Setting text alignment changes the position of the text relative to its insertion point. For example, when a text alignment of ``HPS::Text::Alignment::BottomLeft`` is used, the text is aligned such that the insertion point is at its bottom left. A list of all possible alignment values can be found in the API reference manual under ``HPS::Text::Alignment``.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [020705_a]
		   :end-before: //! [020705_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [020705_a]
		   :end-before: //! [020705_a]

.. image:: images/text_alignment.png

*The text aligned with the insertion point at the bottom left. The red mark is the insertion point.*

Justification controls how the lines of multiline text are displayed relative to other lines in the same text object. Remember that new lines are created through the use of '\n'.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [020705_b]
		   :end-before: //! [020705_b]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [020705_b]
		   :end-before: //! [020705_b]

.. image:: images/justification.png

*The text is right-justified with a center alignment.*

Note the second parameter to ``HPS::TextKey::SetAlignment``, ``HPS::Text::ReferenceFrame::WorldAligned``. This parameter sets the orientation of the text region, and is particularly important when using rotated text. When using a ``WorldAligned`` orientation, the text region is aligned to the world coordinate system. When using a ``PathAligned`` orientation, the text region is oriented to the text's path (shown below, rotated 30 degrees). Note that when transforming text, the transform flag must be set to ``HPS::Text::Transform::Transformable``.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [020705_c]
		   :end-before: //! [020705_c]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [rotated_text]
		   :end-before: //! [rotated_text]

.. image:: images/rotated.png

*A rotated text block*

Another possibility allows you to rotate the text path around the insertion point without rotating the characters. You can do this by assigning a path for the text to follow. However, in most cases, the desired effect is to have the characters rotate along with the entire text block. While you can achieve this same effect using a modelling matrix rotation, this method is useful when you don't want the text to otherwise be affected by segment-level transformations.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [020705_e]
		   :end-before: //! [020705_e]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [020705_e]
		   :end-before: //! [020705_e]
		   
.. image:: images/text_rotation.png

*Rotating text around the insertion point. It rotates text in a counter-clockwise direction starting from the positive X axis.*

Note that the previous result rotates the text alone, and is possible if you aren't using a text background. If you use a text background, the background is not rotated with the text and you could end up with an undesirable result:

.. image:: images/text_rotation_background.png

In order to resolve this issue, you must set the text transform type to ``Transformable``, then rotate the segment:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [text_rotation_background]
		   :end-before: //! [text_rotation_background]

	.. group-tab:: C#
	
		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [text_rotation_background]
		   :end-before: //! [text_rotation_background]
		
This will result in the background being rotated with the text:

.. image:: images/text_rotation_transformed.png


Rotating characters
-------------------

It is also possible to rotate each text character instead of the whole block. To do this, you would replace the call to rotate the modelling matrix with:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_5_abcde.cpp
		   :start-after: //! [020705_d]
		   :end-before: //! [020705_d]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_5_abcde.cs
		   :start-after: //! [020705_d]
		   :end-before: //! [020705_d]

.. image:: images/character_rotation.png

*A text block with characters rotated 40 degrees*


Text Greeking
=============

Text greeking is a rendering optimization that is useful when your scene contains a large amount of text. Text can be slow to render in some circumstances, and when text appears very small on the screen, the trade-off between rendering speed and usefulness is important to consider. Text *greeking* solves this problem by ignoring text that would be drawn below a certain arbitrary size. Alternatively, |HPSNOW| can draw a box or lines in place of the text so there is some indication that text is present, but simply too small to be drawn.

Since text is only subject to zoom when it is transformable, text transforms must be enabled in order for greeking to be useful. The code sample below will enable greeking for text sized below 6 points. 

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_6_a.cpp
		   :start-after: //! [020706_a]
		   :end-before: //! [020706_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_6_a.cs
		   :start-after: //! [020706_a]
		   :end-before: //! [020706_a]


Text Backgrounds
================

|HPSNOW| can draw backgrounds around text automatically. You can control the shape of the background and the width of the margins. Text backgrounds will inherit attributes from the containing segment, which enables you to control the color and edge pattern. Text backgrounds will also wrap properly around transformed text.

The color of the background is that of faces, and the color of the lines around the background is that of edges. So, for example, changing the edge color to blue for the segment which contains the text will change the color of the edges of the text background to blue as well.

There are four pre-defined background shapes: "oval", "ellipse", "rounded box", or "box". It is also possible to define a :ref:`custom shape <prog_guide/0203_text:Custom shapes>`.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [text_background]
		   :end-before: //! [text_background]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [text_background]
		   :end-before: //! [text_background]
		   
.. image:: images/text_background.png

*Text backgrounds may be set to "oval", "ellipse", "rounded box", or "box"*

Additionally, it is possible to style the text background so that it can be of a specific color regardless of the segment's face and edge color. To do this, use the function ``SetBackgroundStyle``. The name passed to this function a :ref:`named style <prog_guide/0403_styles:Named styles>`, which is defined in a portfolio accessible from the containing segment.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [text_background_named_style]
		   :end-before: //! [text_background_named_style]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [text_background_named_style]
		   :end-before: //! [text_background_named_style]


Custom Shapes
-------------

Custom shape backgrounds can also be defined for use with text using a ``HPS::ShapeDefinition``. Shape definitions work like all other definitions in |HPSNOW|:

#. The developer fills out the fields of an ``HPS::ShapeKit`` object to determine how the shape should look
#. The developer uses the ``HPS::ShapeKit`` to define a shape in a portfolio and to give that shape a name
#. The developer uses the name of the shape definition to tell |HPSNOW| which background shape to use

Users define their own shapes by adding one or more shape elements to a ``HPS::ShapeKit``. There are seven different kinds of shape elements:

* polygon
* ellipse
* circle
* elliptical
* circular
* line
* anchor

To define any of these elements, you use a special 2D point class called ``HPS::ShapePoint``. Each ``HPS::ShapePoint`` is made up of two ``HPS::ShapeCoordinate`` objects. Although named ``HPS::ShapeCoordinate``, these objects themselves do not represent an X-Y coordinate until used as part of a ``HPS::ShapePoint``. This is because ``HPS::ShapeCoordinate`` alone is merely a directionless distance.
 
``HPS::ShapeCoordinate`` objects accept up to 5 parameters, which are normalized based on the bounds of the text and its margins. Imagine this is the text you are inserting (the grey box represents the text bounding):

.. image:: images/text_bounding.png

The ``HPS::ShapeCoordinate`` parameters are multiples of the size of the text bounding box. These parameters are summed to form a distance. As an example, consider the following ``HPS::ShapeCoordinate`` objects:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [shape_coordinate1]
		   :end-before: //! [shape_coordinate1]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [shape_coordinate1]
		   :end-before: //! [shape_coordinate1]
		   
Let's imagine the text bounding box is 400 pixels by 150 pixels. The code above means that ``sc1`` will be 400 * 1.15 + 150 * 0 = 460 pixels. ``sc2`` will be 400 * 0.85 + 150 * 1.5 = 565 pixels. ``sp`` will then have X-Y coordinates of (460, 565) relative to the center of the text. The code below uses 100% of the X and Y bounding to locate the corner of the text. Therefore,

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [shape_coordinate2]
		   :end-before: //! [shape_coordinate2]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [shape_coordinate2]
		   :end-before: //! [shape_coordinate2]

...will define this point:

.. image:: images/text_bounding_ex1.png

Similarly, these coordinates...

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [shape_coordinate3]
		   :end-before: //! [shape_coordinate3]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [shape_coordinate3]
		   :end-before: //! [shape_coordinate3]
		   
...define the following location:

.. image:: images/text_bounding_ex2.png

In addition to the normalized X and Y values for the text bounding box, you may optionally specify a radius. The radius works the same way - it is a multiple of the distance from the center of the text to the circle that circumscribes the text bounding box. This is useful if you wish to create a circular background.

Text margins can also be specified. Margins are optional values which the user can set which can be used so that the text background does not hug the text too closely. For example, the default text background looks like this if no margins are used:

.. image:: images/text_background_margins.png

Up to four margin values can be preset by calling the function ``SetBackgroundMargins``. Although called margins, they are simply four values that are added together to the computed ``HPS::ShapeCoordinate`` - *they do not necessarily represent the four sides of the text*. Margin size is relative to the height of the text characters. Margins are set by default to 50% of character height and can be changed using ``HPS::TextAttributeControl::SetBackgroundMargins``.

Use the ``HPS::ShapeCoordinate::SetMargins`` function to define a multiple of how far in each direction the margin will extend, as a *percentage* of the character size. Different margin values are summed to created the final size. For example:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_text_background.cpp
		   :start-after: //! [margins]
		   :end-before: //! [margins]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_text_background.cs
		   :start-after: //! [margins]
		   :end-before: //! [margins]

When the computed value is negative, it will result in the final ``HPS::ShapePoint`` moved in the -X or -Y direction. In the previous snippet, we set the background margins to 40 percent of the character height. Let's imagine the character height for the text we are inserting is 20 pixels. This means:

* sc1 margin size is 0.4 * 20 = 8 pixels
* sc2 margin size is 2.0 * 20 = 40 pixels
* sc3 margin size is -0.4 * 20 = -8 pixels
* sc4 margin size is -2.5 * 20 = -20 pixels

The computed margin value is added with the normalized X and Y values for the text bounding box as well as any radius value that has been specified. You typically will not use all possible combinations of parameters when creating these shapes, only those which are necessary to create the shape you need. At this point, we have all the information we need to start creating custom shapes. For example, this is how you create a modified rectangle shape with clipped edges:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_custom_text_background.cpp
		   :start-after: //! [custom_text_background]
		   :end-before: //! [custom_text_background]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_custom_text_background.cs
		   :start-after: //! [custom_text_background]
		   :end-before: //! [custom_text_background]
		   
.. image:: images/custom_text_background.png


Using GD&T Symbols
==================

Geometry, Dimension & Tolerance [GD&T] symbols are used by the engineering industry to delineate geometric features that would be cumbersome to otherwise describe. |HPSNOW| supports the use of such symbols, provided you are using a font which defines them. The "ts3d" font, distributed with |HPSNOW|, is such a font. As the symbols are outside the ASCII character set, you must make sure they are UTF-8 encoded when inserting them. The ``HPS::UTF8`` class is provided to facilitate the encoding. In C#, simply use the ``String`` object. The following code sample demonstrates how to do this:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_2_7_7_a.cpp
		   :start-after: //! [020707_a]
		   :end-before: //! [020707_a]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_2_7_7_a.cs
		   :start-after: //! [020707_a]
		   :end-before: //! [020707_a]
		   
For a list of all GD&T symbols, see :doc:`the appendix <appendix_gdt>`.


Working With Non-Latin Characters
=================================

If you're using non-Latin characters, such as Chinese or Hebrew, please note that the "stroked" and "ts3d" fonts don't provide these characters. For Windows users, fonts that support non-Latin characters are usually available in the system's font directory; for Ubuntu users, available fonts are located in */usr/share/fonts*.

Here is an example of how to change the font to one that supports Chinese characters:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00700_non_latin_fonts.cpp
		   :start-after: //! [non_latin_fonts]
		   :end-before: //! [non_latin_fonts]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00700_non_latin_fonts.cs
		   :start-after: //! [non_latin_fonts]
		   :end-before: //! [non_latin_fonts]

One current limitation is that GD&T symbols aren't supported by many of the commonly used system fonts, so if you're using GD&T symbols, it's important to find a font that supports your language of choice as well as GD&T symbols, or to create a workflow that alternates between the fonts required for your language and GD&T symbols.

