33 : character (c), path (p), width (w)
43 void addKerningPair (
juce_wchar subsequentCharacter,
float extraKerningAmount)
noexcept
45 kerningPairs.add ({ subsequentCharacter, extraKerningAmount });
48 float getHorizontalSpacing (
juce_wchar subsequentCharacter)
const noexcept
50 if (subsequentCharacter != 0)
51 for (
auto& kp : kerningPairs)
52 if (kp.character2 == subsequentCharacter)
53 return width + kp.kerningAmount;
61 Array<KerningPair> kerningPairs;
68namespace CustomTypefaceHelpers
74 if (n >= 0xd800 && n <= 0xdfff)
79 n = 0x10000 + (((n - 0xd800) << 10) | (nextWord - 0xdc00));
85 static void writeChar (OutputStream& out,
juce_wchar charToWrite)
87 if (charToWrite >= 0x10000)
89 charToWrite -= 0x10000;
90 out.writeShort ((
short) (
uint16) (0xd800 + (charToWrite >> 10)));
91 out.writeShort ((
short) (
uint16) (0xdc00 + (charToWrite & 0x3ff)));
95 out.writeShort ((
short) (
uint16) charToWrite);
118 const bool isItalic = in.
readBool();
119 style = FontStyleHelpers::getStyleName (isBold, isItalic);
122 defaultCharacter = CustomTypefaceHelpers::readChar (in);
126 for (
int i = 0; i < numChars; ++i)
128 auto c = CustomTypefaceHelpers::readChar (in);
136 auto numKerningPairs = in.
readInt();
138 for (
int i = 0; i < numKerningPairs; ++i)
140 auto char1 = CustomTypefaceHelpers::readChar (in);
141 auto char2 = CustomTypefaceHelpers::readChar (in);
154 defaultCharacter = 0;
157 zeromem (lookupTable,
sizeof (lookupTable));
162 bool isItalic,
juce_wchar newDefaultCharacter)
noexcept
165 defaultCharacter = newDefaultCharacter;
167 style = FontStyleHelpers::getStyleName (isBold, isItalic);
171 float newAscent,
juce_wchar newDefaultCharacter)
noexcept
175 defaultCharacter = newDefaultCharacter;
182 jassert (findGlyph (character,
false) ==
nullptr);
185 lookupTable [character] = (
short) glyphs.size();
187 glyphs.add (
new GlyphInfo (character, path, width));
194 if (
auto* g = findGlyph (char1,
true))
195 g->addKerningPair (char2, extraAmount);
204 return glyphs [(
int) lookupTable [(
int) character]];
206 for (
auto* g : glyphs)
207 if (g->character == character)
210 if (loadIfNeeded && loadGlyphIfPossible (character))
211 return findGlyph (character,
false);
223 setCharacteristics (name, style, typefaceToCopy.getAscent(), defaultCharacter);
225 for (
int i = 0; i < numCharacters; ++i)
233 const int glyphIndex = glyphIndexes.
getFirst();
235 if (glyphIndex >= 0 && glyphIndexes.
size() > 0)
237 auto glyphWidth = offsets[1];
240 typefaceToCopy.getOutlineForGlyph (glyphIndex, p);
242 addGlyph (c, p, glyphWidth);
244 for (
int j = glyphs.size() - 1; --j >= 0;)
246 auto char2 = glyphs.getUnchecked (j)->character;
251 if (offsets.
size() > 1)
252 addKerningPair (c, char2, offsets[1] - glyphWidth);
263 out.
writeBool (FontStyleHelpers::isBold (style));
264 out.
writeBool (FontStyleHelpers::isItalic (style));
266 CustomTypefaceHelpers::writeChar (out, defaultCharacter);
269 int numKerningPairs = 0;
271 for (
auto* g : glyphs)
273 CustomTypefaceHelpers::writeChar (out, g->character);
275 g->path.writePathToStream (out);
277 numKerningPairs += g->kerningPairs.size();
282 for (
auto* g : glyphs)
284 for (
auto& p : g->kerningPairs)
286 CustomTypefaceHelpers::writeChar (out, g->character);
287 CustomTypefaceHelpers::writeChar (out, p.character2);
306 auto c = t.getAndAdvance();
308 if (
auto* glyph = findGlyph (c,
true))
310 x += glyph->getHorizontalSpacing (*t);
314 if (
auto fallbackTypeface = Typeface::getFallbackTypeface())
315 if (fallbackTypeface.get() !=
this)
333 auto c = t.getAndAdvance();
335 if (
auto* glyph = findGlyph (c,
true))
337 width = glyph->getHorizontalSpacing (*t);
338 glyphChar = (
int) glyph->character;
342 auto fallbackTypeface = getFallbackTypeface();
344 if (fallbackTypeface !=
nullptr && fallbackTypeface.get() !=
this)
350 if (subGlyphs.
size() > 0)
353 width = subOffsets[1];
359 resultGlyphs.
add (glyphChar);
366 if (
auto* glyph = findGlyph ((
juce_wchar) glyphNumber,
true))
372 if (
auto fallbackTypeface = getFallbackTypeface())
373 if (fallbackTypeface.get() !=
this)
374 return fallbackTypeface->getOutlineForGlyph (glyphNumber, path);
381 if (
auto* glyph = findGlyph ((
juce_wchar) glyphNumber,
true))
383 if (! glyph->path.isEmpty())
384 return new EdgeTable (glyph->path.getBoundsTransformed (transform)
385 .getSmallestIntegerContainer().expanded (1, 0),
386 glyph->path, transform);
390 if (
auto fallbackTypeface = getFallbackTypeface())
391 if (fallbackTypeface.get() !=
this)
392 return fallbackTypeface->getEdgeTableForGlyph (glyphNumber, transform, fontHeight);
Holds a resizable array of primitive or copy-by-value objects.
void clearQuick()
Removes all elements from the array without freeing the array's allocated storage.
int size() const noexcept
Returns the current number of elements in the array.
ElementType getFirst() const noexcept
Returns the first element in the array, or a default value if the array is empty.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
void clear()
Resets this typeface, deleting all its glyphs and settings.
float getHeightToPointsFactor() const override
Returns the value by which you should multiply a JUCE font-height value to convert it to the equivale...
CustomTypeface()
Creates a new, empty typeface.
float getAscent() const override
Returns the ascent of the font, as a proportion of its height.
float getDescent() const override
Returns the descent of the font, as a proportion of its height.
virtual bool loadGlyphIfPossible(juce_wchar characterNeeded)
If a subclass overrides this, it can load glyphs into the font on-demand.
void addKerningPair(juce_wchar char1, juce_wchar char2, float extraAmount) noexcept
Specifies an extra kerning amount to be used between a pair of characters.
void addGlyphsFromOtherTypeface(Typeface &typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) noexcept
Adds a range of glyphs from another typeface.
void setCharacteristics(const String &fontFamily, float ascent, bool isBold, bool isItalic, juce_wchar defaultCharacter) noexcept
Sets the vital statistics for the typeface.
void getGlyphPositions(const String &, Array< int > &glyphs, Array< float > &xOffsets) override
Converts a line of text into its glyph numbers and their positions.
float getStringWidth(const String &) override
Measures the width of a line of text.
~CustomTypeface() override
Destructor.
bool getOutlineForGlyph(int glyphNumber, Path &) override
Returns the outline for a glyph.
EdgeTable * getEdgeTableForGlyph(int glyphNumber, const AffineTransform &, float fontHeight) override
Returns a new EdgeTable that contains the path for the given glyph, with the specified transform appl...
void addGlyph(juce_wchar character, const Path &path, float width) noexcept
Adds a glyph to the typeface.
bool writeToStream(OutputStream &outputStream)
Saves this typeface as a Juce-formatted font file.
A table of horizontal scan-line segments - used for rasterising Paths.
A stream which uses zlib to compress the data written into it.
The base class for streams that write data to some kind of destination.
virtual bool writeFloat(float value)
Writes a 32-bit floating point value to the stream in a binary format.
virtual bool writeBool(bool boolValue)
Writes a boolean to the stream as a single byte.
virtual bool writeInt(int value)
Writes a 32-bit integer to the stream in a little-endian byte order.
virtual bool writeString(const String &text)
Stores a string in the stream in a binary format.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
void loadPathFromStream(InputStream &source)
Loads a stored path from a data stream.
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
static String charToString(juce_wchar character)
Creates a string from a single character.
A typeface represents a size-independent font.
unsigned short uint16
A platform-independent 16-bit unsigned integer type.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.
void zeromem(void *memory, size_t numBytes) noexcept
Fills a block of memory with zeros.