LMMS
Loading...
Searching...
No Matches
juce_CustomTypeface.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
31public:
33 : character (c), path (p), width (w)
34 {
35 }
36
42
43 void addKerningPair (juce_wchar subsequentCharacter, float extraKerningAmount) noexcept
44 {
45 kerningPairs.add ({ subsequentCharacter, extraKerningAmount });
46 }
47
48 float getHorizontalSpacing (juce_wchar subsequentCharacter) const noexcept
49 {
50 if (subsequentCharacter != 0)
51 for (auto& kp : kerningPairs)
52 if (kp.character2 == subsequentCharacter)
53 return width + kp.kerningAmount;
54
55 return width;
56 }
57
59 const Path path;
60 float width;
62
63private:
65};
66
67//==============================================================================
69{
71 {
72 auto n = (uint32) (uint16) in.readShort();
73
74 if (n >= 0xd800 && n <= 0xdfff)
75 {
76 auto nextWord = (uint32) (uint16) in.readShort();
77 jassert (nextWord >= 0xdc00); // illegal unicode character!
78
79 n = 0x10000 + (((n - 0xd800) << 10) | (nextWord - 0xdc00));
80 }
81
82 return (juce_wchar) n;
83 }
84
85 static void writeChar (OutputStream& out, juce_wchar charToWrite)
86 {
87 if (charToWrite >= 0x10000)
88 {
89 charToWrite -= 0x10000;
90 out.writeShort ((short) (uint16) (0xd800 + (charToWrite >> 10)));
91 out.writeShort ((short) (uint16) (0xdc00 + (charToWrite & 0x3ff)));
92 }
93 else
94 {
95 out.writeShort ((short) (uint16) charToWrite);
96 }
97 }
98}
99
100//==============================================================================
106
108 : Typeface (String(), String())
109{
110 clear();
111
112 GZIPDecompressorInputStream gzin (serialisedTypefaceStream);
113 BufferedInputStream in (gzin, 32768);
114
115 name = in.readString();
116
117 const bool isBold = in.readBool();
118 const bool isItalic = in.readBool();
119 style = FontStyleHelpers::getStyleName (isBold, isItalic);
120
121 ascent = in.readFloat();
123
124 auto numChars = in.readInt();
125
126 for (int i = 0; i < numChars; ++i)
127 {
129 auto width = in.readFloat();
130
131 Path p;
132 p.loadPathFromStream (in);
133 addGlyph (c, p, width);
134 }
135
136 auto numKerningPairs = in.readInt();
137
138 for (int i = 0; i < numKerningPairs; ++i)
139 {
140 auto char1 = CustomTypefaceHelpers::readChar (in);
141 auto char2 = CustomTypefaceHelpers::readChar (in);
142
143 addKerningPair (char1, char2, in.readFloat());
144 }
145}
146
150
151//==============================================================================
153{
155 ascent = 1.0f;
156 style = "Regular";
157 zeromem (lookupTable, sizeof (lookupTable));
158 glyphs.clear();
159}
160
161void CustomTypeface::setCharacteristics (const String& newName, float newAscent, bool isBold,
162 bool isItalic, juce_wchar newDefaultCharacter) noexcept
163{
164 name = newName;
165 defaultCharacter = newDefaultCharacter;
166 ascent = newAscent;
167 style = FontStyleHelpers::getStyleName (isBold, isItalic);
168}
169
170void CustomTypeface::setCharacteristics (const String& newName, const String& newStyle,
171 float newAscent, juce_wchar newDefaultCharacter) noexcept
172{
173 name = newName;
174 style = newStyle;
175 defaultCharacter = newDefaultCharacter;
176 ascent = newAscent;
177}
178
179void CustomTypeface::addGlyph (juce_wchar character, const Path& path, float width) noexcept
180{
181 // Check that you're not trying to add the same character twice..
182 jassert (findGlyph (character, false) == nullptr);
183
184 if (isPositiveAndBelow ((int) character, numElementsInArray (lookupTable)))
185 lookupTable [character] = (short) glyphs.size();
186
187 glyphs.add (new GlyphInfo (character, path, width));
188}
189
190void CustomTypeface::addKerningPair (juce_wchar char1, juce_wchar char2, float extraAmount) noexcept
191{
192 if (extraAmount != 0.0f)
193 {
194 if (auto* g = findGlyph (char1, true))
195 g->addKerningPair (char2, extraAmount);
196 else
197 jassertfalse; // can only add kerning pairs for characters that exist!
198 }
199}
200
201CustomTypeface::GlyphInfo* CustomTypeface::findGlyph (juce_wchar character, bool loadIfNeeded) noexcept
202{
203 if (isPositiveAndBelow ((int) character, numElementsInArray (lookupTable)) && lookupTable [character] > 0)
204 return glyphs [(int) lookupTable [(int) character]];
205
206 for (auto* g : glyphs)
207 if (g->character == character)
208 return g;
209
210 if (loadIfNeeded && loadGlyphIfPossible (character))
211 return findGlyph (character, false);
212
213 return nullptr;
214}
215
217{
218 return false;
219}
220
221void CustomTypeface::addGlyphsFromOtherTypeface (Typeface& typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) noexcept
222{
223 setCharacteristics (name, style, typefaceToCopy.getAscent(), defaultCharacter);
224
225 for (int i = 0; i < numCharacters; ++i)
226 {
227 auto c = (juce_wchar) (characterStartIndex + static_cast<juce_wchar> (i));
228
229 Array<int> glyphIndexes;
230 Array<float> offsets;
231 typefaceToCopy.getGlyphPositions (String::charToString (c), glyphIndexes, offsets);
232
233 const int glyphIndex = glyphIndexes.getFirst();
234
235 if (glyphIndex >= 0 && glyphIndexes.size() > 0)
236 {
237 auto glyphWidth = offsets[1];
238
239 Path p;
240 typefaceToCopy.getOutlineForGlyph (glyphIndex, p);
241
242 addGlyph (c, p, glyphWidth);
243
244 for (int j = glyphs.size() - 1; --j >= 0;)
245 {
246 auto char2 = glyphs.getUnchecked (j)->character;
247 glyphIndexes.clearQuick();
248 offsets.clearQuick();
249 typefaceToCopy.getGlyphPositions (String::charToString (c) + String::charToString (char2), glyphIndexes, offsets);
250
251 if (offsets.size() > 1)
252 addKerningPair (c, char2, offsets[1] - glyphWidth);
253 }
254 }
255 }
256}
257
259{
260 GZIPCompressorOutputStream out (outputStream);
261
262 out.writeString (name);
263 out.writeBool (FontStyleHelpers::isBold (style));
265 out.writeFloat (ascent);
267 out.writeInt (glyphs.size());
268
269 int numKerningPairs = 0;
270
271 for (auto* g : glyphs)
272 {
274 out.writeFloat (g->width);
275 g->path.writePathToStream (out);
276
277 numKerningPairs += g->kerningPairs.size();
278 }
279
280 out.writeInt (numKerningPairs);
281
282 for (auto* g : glyphs)
283 {
284 for (auto& p : g->kerningPairs)
285 {
288 out.writeFloat (p.kerningAmount);
289 }
290 }
291
292 return true;
293}
294
295//==============================================================================
296float CustomTypeface::getAscent() const { return ascent; }
297float CustomTypeface::getDescent() const { return 1.0f - ascent; }
299
301{
302 float x = 0;
303
304 for (auto t = text.getCharPointer(); ! t.isEmpty();)
305 {
306 auto c = t.getAndAdvance();
307
308 if (auto* glyph = findGlyph (c, true))
309 {
310 x += glyph->getHorizontalSpacing (*t);
311 }
312 else
313 {
314 if (auto fallbackTypeface = Typeface::getFallbackTypeface())
315 if (fallbackTypeface.get() != this)
316 x += fallbackTypeface->getStringWidth (String::charToString (c));
317 }
318 }
319
320 return x;
321}
322
324{
325 xOffsets.add (0);
326 float x = 0;
327
328 for (auto t = text.getCharPointer(); ! t.isEmpty();)
329 {
330 float width = 0.0f;
331 int glyphChar = 0;
332
333 auto c = t.getAndAdvance();
334
335 if (auto* glyph = findGlyph (c, true))
336 {
337 width = glyph->getHorizontalSpacing (*t);
338 glyphChar = (int) glyph->character;
339 }
340 else
341 {
342 auto fallbackTypeface = getFallbackTypeface();
343
344 if (fallbackTypeface != nullptr && fallbackTypeface.get() != this)
345 {
346 Array<int> subGlyphs;
347 Array<float> subOffsets;
348 fallbackTypeface->getGlyphPositions (String::charToString (c), subGlyphs, subOffsets);
349
350 if (subGlyphs.size() > 0)
351 {
352 glyphChar = subGlyphs.getFirst();
353 width = subOffsets[1];
354 }
355 }
356 }
357
358 x += width;
359 resultGlyphs.add (glyphChar);
360 xOffsets.add (x);
361 }
362}
363
364bool CustomTypeface::getOutlineForGlyph (int glyphNumber, Path& path)
365{
366 if (auto* glyph = findGlyph ((juce_wchar) glyphNumber, true))
367 {
368 path = glyph->path;
369 return true;
370 }
371
372 if (auto fallbackTypeface = getFallbackTypeface())
373 if (fallbackTypeface.get() != this)
374 return fallbackTypeface->getOutlineForGlyph (glyphNumber, path);
375
376 return false;
377}
378
379EdgeTable* CustomTypeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransform& transform, float fontHeight)
380{
381 if (auto* glyph = findGlyph ((juce_wchar) glyphNumber, true))
382 {
383 if (! glyph->path.isEmpty())
384 return new EdgeTable (glyph->path.getBoundsTransformed (transform)
385 .getSmallestIntegerContainer().expanded (1, 0),
386 glyph->path, transform);
387 }
388 else
389 {
390 if (auto fallbackTypeface = getFallbackTypeface())
391 if (fallbackTypeface.get() != this)
392 return fallbackTypeface->getEdgeTableForGlyph (glyphNumber, transform, fontHeight);
393 }
394
395 return nullptr;
396}
397
398} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
Definition juce_AffineTransform.h:43
Definition juce_Array.h:56
void clearQuick()
Definition juce_Array.h:198
int size() const noexcept
Definition juce_Array.h:215
ElementType getFirst() const noexcept
Definition juce_Array.h:290
void add(const ElementType &newElement)
Definition juce_Array.h:418
Definition juce_BufferedInputStream.h:37
Definition juce_CustomTypeface.cpp:30
float width
Definition juce_CustomTypeface.cpp:60
Array< KerningPair > kerningPairs
Definition juce_CustomTypeface.cpp:61
float getHorizontalSpacing(juce_wchar subsequentCharacter) const noexcept
Definition juce_CustomTypeface.cpp:48
const juce_wchar character
Definition juce_CustomTypeface.cpp:58
void addKerningPair(juce_wchar subsequentCharacter, float extraKerningAmount) noexcept
Definition juce_CustomTypeface.cpp:43
GlyphInfo(juce_wchar c, const Path &p, float w) noexcept
Definition juce_CustomTypeface.cpp:32
const Path path
Definition juce_CustomTypeface.cpp:59
GlyphInfo * findGlyph(const juce_wchar character, bool loadIfNeeded) noexcept
Definition juce_CustomTypeface.cpp:201
void clear()
Definition juce_CustomTypeface.cpp:152
float ascent
Definition juce_CustomTypeface.h:143
float getHeightToPointsFactor() const override
Definition juce_CustomTypeface.cpp:298
juce_wchar defaultCharacter
Definition juce_CustomTypeface.h:142
CustomTypeface()
Definition juce_CustomTypeface.cpp:101
float getAscent() const override
Definition juce_CustomTypeface.cpp:296
float getDescent() const override
Definition juce_CustomTypeface.cpp:297
virtual bool loadGlyphIfPossible(juce_wchar characterNeeded)
Definition juce_CustomTypeface.cpp:216
void addKerningPair(juce_wchar char1, juce_wchar char2, float extraAmount) noexcept
Definition juce_CustomTypeface.cpp:190
void addGlyphsFromOtherTypeface(Typeface &typefaceToCopy, juce_wchar characterStartIndex, int numCharacters) noexcept
Definition juce_CustomTypeface.cpp:221
void setCharacteristics(const String &fontFamily, float ascent, bool isBold, bool isItalic, juce_wchar defaultCharacter) noexcept
Definition juce_CustomTypeface.cpp:161
OwnedArray< GlyphInfo > glyphs
Definition juce_CustomTypeface.h:157
void getGlyphPositions(const String &, Array< int > &glyphs, Array< float > &xOffsets) override
Definition juce_CustomTypeface.cpp:323
float getStringWidth(const String &) override
Definition juce_CustomTypeface.cpp:300
~CustomTypeface() override
Definition juce_CustomTypeface.cpp:147
bool getOutlineForGlyph(int glyphNumber, Path &) override
Definition juce_CustomTypeface.cpp:364
short lookupTable[128]
Definition juce_CustomTypeface.h:158
EdgeTable * getEdgeTableForGlyph(int glyphNumber, const AffineTransform &, float fontHeight) override
Definition juce_CustomTypeface.cpp:379
void addGlyph(juce_wchar character, const Path &path, float width) noexcept
Definition juce_CustomTypeface.cpp:179
bool writeToStream(OutputStream &outputStream)
Definition juce_CustomTypeface.cpp:258
Definition juce_EdgeTable.h:38
Definition juce_GZIPCompressorOutputStream.h:39
Definition juce_GZIPDecompressorInputStream.h:39
Definition juce_InputStream.h:37
Definition juce_OutputStream.h:38
Definition juce_Path.h:65
Definition juce_String.h:53
static String charToString(juce_wchar character)
Definition juce_String.cpp:359
static Ptr getFallbackTypeface()
Definition juce_Typeface.cpp:115
String style
Definition juce_Typeface.h:147
Typeface(const String &name, const String &style) noexcept
Definition juce_Typeface.cpp:108
String name
Definition juce_Typeface.h:147
UINT_D64 w
Definition inflate.c:942
struct huft * t
Definition inflate.c:943
register unsigned j
Definition inflate.c:1576
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
static int width
Definition pugl.h:1593
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
Definition juce_CustomTypeface.cpp:69
static juce_wchar readChar(InputStream &in)
Definition juce_CustomTypeface.cpp:70
static void writeChar(OutputStream &out, juce_wchar charToWrite)
Definition juce_CustomTypeface.cpp:85
Definition carla_juce.cpp:31
unsigned short uint16
Definition juce_MathsFunctions.h:41
unsigned int uint32
Definition juce_MathsFunctions.h:45
wchar_t juce_wchar
Definition juce_CharacterFunctions.h:42
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
constexpr int numElementsInArray(Type(&)[N]) noexcept
Definition juce_MathsFunctions.h:344
void zeromem(void *memory, size_t numBytes) noexcept
Definition juce_Memory.h:28
Definition juce_CustomTypeface.cpp:38
juce_wchar character2
Definition juce_CustomTypeface.cpp:39
float kerningAmount
Definition juce_CustomTypeface.cpp:40
static bool isItalic(const String &style) noexcept
Definition juce_Typeface.cpp:51
static bool isBold(const String &style) noexcept
Definition juce_Typeface.cpp:46
static const char * getStyleName(const bool bold, const bool italic) noexcept
Definition juce_Typeface.cpp:31
const char * text
Definition swell-functions.h:167
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
typedef int(UZ_EXP MsgFn)()