mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
Initial (WIP) Harfbuzz text shaping integration.
This a significant refactor / rewrite of much of the love.graphics Font code. Text positioning is now split into TextShaper classes in the love.font module. This isn't exposed to users yet. BMFonts and ImageFonts use the same text shaping as before (in the new TextShaper API). Fonts loaded via FreeType now use Harfbuzz for text shaping. The new code isn't at feature-parity with the old code yet. Harfbuzz-based text shaping enables kerning support in more fonts, character combining into ligature glyphs, and directions other than left-to-right (this isn't supported in love yet).
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright (c) 2006-2022 LOVE Development Team
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
// LOVE
|
||||
#include "common/Object.h"
|
||||
#include "common/Vector.h"
|
||||
#include "common/int.h"
|
||||
#include "common/Color.h"
|
||||
#include "common/Range.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace font
|
||||
{
|
||||
|
||||
class Rasterizer;
|
||||
|
||||
struct ColoredString
|
||||
{
|
||||
std::string str;
|
||||
Colorf color;
|
||||
};
|
||||
|
||||
struct IndexedColor
|
||||
{
|
||||
Colorf color;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct ColoredCodepoints
|
||||
{
|
||||
std::vector<uint32> cps;
|
||||
std::vector<IndexedColor> colors;
|
||||
};
|
||||
|
||||
void getCodepointsFromString(const std::string& str, std::vector<uint32>& codepoints);
|
||||
void getCodepointsFromString(const std::vector<ColoredString>& strs, ColoredCodepoints& codepoints);
|
||||
|
||||
class TextShaper : public Object
|
||||
{
|
||||
public:
|
||||
|
||||
struct GlyphIndex
|
||||
{
|
||||
int index;
|
||||
int rasterizerIndex;
|
||||
};
|
||||
|
||||
struct GlyphPosition
|
||||
{
|
||||
Vector2 position;
|
||||
GlyphIndex glyphIndex;
|
||||
};
|
||||
|
||||
struct TextInfo
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
static love::Type type;
|
||||
|
||||
virtual ~TextShaper();
|
||||
|
||||
const std::vector<StrongRef<Rasterizer>> &getRasterizers() const { return rasterizers; }
|
||||
|
||||
float getHeight() const;
|
||||
|
||||
/**
|
||||
* Sets the line height (which should be a number to multiply the font size by,
|
||||
* example: line height = 1.2 and size = 12 means that rendered line height = 12*1.2)
|
||||
* @param height The new line height.
|
||||
**/
|
||||
void setLineHeight(float height);
|
||||
|
||||
/**
|
||||
* Returns the line height.
|
||||
**/
|
||||
float getLineHeight() const;
|
||||
|
||||
// Extra font metrics
|
||||
int getAscent() const;
|
||||
int getDescent() const;
|
||||
float getBaseline() const;
|
||||
|
||||
bool hasGlyph(uint32 glyph) const;
|
||||
bool hasGlyphs(const std::string &text) const;
|
||||
|
||||
float getKerning(uint32 leftglyph, uint32 rightglyph);
|
||||
float getKerning(const std::string& leftchar, const std::string& rightchar);
|
||||
|
||||
int getGlyphAdvance(uint32 glyph, GlyphIndex *glyphindex = nullptr);
|
||||
|
||||
int getWidth(const std::string &str);
|
||||
|
||||
void getWrap(const std::vector<ColoredString>& text, float wraplimit, std::vector<std::string>& lines, std::vector<int>* line_widths = nullptr);
|
||||
void getWrap(const ColoredCodepoints& codepoints, float wraplimit, std::vector<Range> &lineranges, std::vector<int> *linewidths = nullptr);
|
||||
|
||||
virtual void setFallbacks(const std::vector<Rasterizer *> &fallbacks);
|
||||
|
||||
virtual void computeGlyphPositions(const ColoredCodepoints &codepoints, Range range, Vector2 offset, float extraspacing, std::vector<GlyphPosition> *positions, std::vector<IndexedColor> *colors, TextInfo *info) = 0;
|
||||
virtual int computeWordWrapIndex(const ColoredCodepoints& codepoints, Range range, float wraplimit, float *width) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
TextShaper(Rasterizer *rasterizer);
|
||||
|
||||
std::vector<StrongRef<Rasterizer>> rasterizers;
|
||||
std::vector<float> dpiScales;
|
||||
|
||||
private:
|
||||
|
||||
int height;
|
||||
float lineHeight;
|
||||
|
||||
// maps glyphs to advance and glyph+rasterizer index.
|
||||
std::unordered_map<uint32, std::pair<int, GlyphIndex>> glyphAdvances;
|
||||
|
||||
// map of left/right glyph pairs to horizontal kerning.
|
||||
std::unordered_map<uint64, float> kerning;
|
||||
|
||||
}; // TextShaper
|
||||
|
||||
} // font
|
||||
} // love
|
||||
Reference in New Issue
Block a user