|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* This file is part of libbluray
|
|
Packit |
5e46da |
* Copyright (C) 2013 Petri Hintukainen <phintuka@users.sourceforge.net>
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is free software; you can redistribute it and/or
|
|
Packit |
5e46da |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License as published by the Free Software Foundation; either
|
|
Packit |
5e46da |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
5e46da |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
5e46da |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
5e46da |
* Lesser General Public License for more details.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License along with this library. If not, see
|
|
Packit |
5e46da |
* <http://www.gnu.org/licenses/>.
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#if HAVE_CONFIG_H
|
|
Packit |
5e46da |
#include "config.h"
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "util/macro.h"
|
|
Packit |
5e46da |
#include "util/logging.h"
|
|
Packit |
5e46da |
#include "bluray.h" /* bd_char_code_e */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include <stdint.h>
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
#include <ft2build.h>
|
|
Packit |
5e46da |
#include FT_FREETYPE_H
|
|
Packit |
5e46da |
#include FT_SYNTHESIS_H
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "textst_render.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#define TEXTST_ERROR(...) BD_DEBUG(DBG_GC | DBG_CRIT, __VA_ARGS__)
|
|
Packit |
5e46da |
#define TEXTST_TRACE(...) BD_DEBUG(DBG_GC, __VA_ARGS__)
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* data
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
typedef struct {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
FT_Face face;
|
|
Packit |
5e46da |
void *mem;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
} FONT_DATA;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
struct textst_render {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
FT_Library ft_lib;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
unsigned font_count;
|
|
Packit |
5e46da |
FONT_DATA *font;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
bd_char_code_e char_code;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
};
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* init / free
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
TEXTST_RENDER *textst_render_init(void)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
TEXTST_RENDER *p = calloc(1, sizeof(TEXTST_RENDER));
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!p) {
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!FT_Init_FreeType(&p->ft_lib)) {
|
|
Packit |
5e46da |
return p;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
X_FREE(p);
|
|
Packit |
5e46da |
TEXTST_ERROR("Loading FreeType2 failed\n");
|
|
Packit |
5e46da |
#else
|
|
Packit |
5e46da |
TEXTST_ERROR("TextST font support not compiled in\n");
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
void textst_render_free(TEXTST_RENDER **pp)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (pp && *pp) {
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
TEXTST_RENDER *p = *pp;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (p->ft_lib) {
|
|
Packit |
5e46da |
/* free fonts */
|
|
Packit |
5e46da |
unsigned ii;
|
|
Packit |
5e46da |
for (ii = 0; ii < p->font_count; ii++) {
|
|
Packit |
5e46da |
if (p->font[ii].face) {
|
|
Packit |
5e46da |
FT_Done_Face(p->font[ii].face);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
X_FREE(p->font[ii].mem);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
X_FREE(p->font);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
FT_Done_FreeType(p->ft_lib);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
X_FREE(*pp);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* settings
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
int textst_render_add_font(TEXTST_RENDER *p, void *data, size_t size)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
FONT_DATA *tmp = realloc(p->font, sizeof(*(p->font)) * (p->font_count + 1));
|
|
Packit |
5e46da |
if (!tmp) {
|
|
Packit |
5e46da |
TEXTST_ERROR("out of memory\n");
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
p->font = tmp;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (FT_New_Memory_Face(p->ft_lib, (const FT_Byte*)data, (FT_Long)size, -1, NULL)) {
|
|
Packit |
5e46da |
TEXTST_ERROR("Unsupport font file format\n");
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!FT_New_Memory_Face(p->ft_lib, (const FT_Byte*)data, (FT_Long)size, 0, &p->font[p->font_count].face)) {
|
|
Packit |
5e46da |
p->font[p->font_count].mem = data;
|
|
Packit |
5e46da |
p->font_count++;
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
TEXTST_ERROR("Loading font %d failed\n", p->font_count);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#else
|
|
Packit |
5e46da |
(void)p;
|
|
Packit |
5e46da |
(void)data;
|
|
Packit |
5e46da |
(void)size;
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
int textst_render_set_char_code(TEXTST_RENDER *p, int char_code)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
p->char_code = (bd_char_code_e)char_code;
|
|
Packit |
5e46da |
if (p->char_code != BLURAY_TEXT_CHAR_CODE_UTF8) {
|
|
Packit |
5e46da |
TEXTST_ERROR("WARNING: unsupported TextST coding type %d\n", char_code);
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#else
|
|
Packit |
5e46da |
(void)p;
|
|
Packit |
5e46da |
(void)char_code;
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* UTF-8
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int _utf8_char_size(const uint8_t *s)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if ((s[0] & 0xE0) == 0xC0 &&
|
|
Packit |
5e46da |
(s[1] & 0xC0) == 0x80) {
|
|
Packit |
5e46da |
return 2;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if ((s[0] & 0xF0) == 0xE0 &&
|
|
Packit |
5e46da |
(s[1] & 0xC0) == 0x80 &&
|
|
Packit |
5e46da |
(s[2] & 0xC0) == 0x80) {
|
|
Packit |
5e46da |
return 3;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if ((s[0] & 0xF8) == 0xF0 &&
|
|
Packit |
5e46da |
(s[1] & 0xC0) == 0x80 &&
|
|
Packit |
5e46da |
(s[2] & 0xC0) == 0x80 &&
|
|
Packit |
5e46da |
(s[3] & 0xC0) == 0x80) {
|
|
Packit |
5e46da |
return 4;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static unsigned _utf8_char_get(const uint8_t *s, int char_size)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (!char_size) {
|
|
Packit |
5e46da |
char_size = _utf8_char_size(s);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
switch (char_size) {
|
|
Packit |
5e46da |
case 2: return ((s[0] & 0x1F) << 6) | ((s[1] & 0x3F));
|
|
Packit |
5e46da |
case 3: return ((s[0] & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | ((s[2] & 0x3F));
|
|
Packit |
5e46da |
case 4: return ((s[0] & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[2] & 0x3F) << 6) | ((s[3] & 0x3F));
|
|
Packit |
5e46da |
default: ;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return s[0];
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#endif /* HAVE_FT2 */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* rendering
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int _draw_string(FT_Face face, const uint8_t *string, int length,
|
|
Packit |
5e46da |
TEXTST_BITMAP *bmp, int x, int y,
|
|
Packit |
5e46da |
BD_TEXTST_REGION_STYLE *style,
|
|
Packit |
5e46da |
int *baseline_pos)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint8_t color = style->font_color;
|
|
Packit |
5e46da |
unsigned char_code;
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
unsigned jj, kk;
|
|
Packit |
5e46da |
unsigned flags;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (length <= 0) {
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (!bmp) {
|
|
Packit |
5e46da |
flags = FT_LOAD_DEFAULT;
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
flags = FT_LOAD_RENDER;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
for (ii = 0; ii < length; ii++) {
|
|
Packit |
5e46da |
/*if (p->char_code == BLURAY_TEXT_CHAR_CODE_UTF8) {*/
|
|
Packit |
5e46da |
int char_size = _utf8_char_size(string + ii);
|
|
Packit |
5e46da |
char_code = _utf8_char_get(string + ii, char_size);
|
|
Packit |
5e46da |
ii += char_size - 1;
|
|
Packit |
5e46da |
/*}*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (FT_Load_Char(face, char_code, flags /*| FT_LOAD_MONOCHROME*/) == 0) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (style->font_style.bold && !(face->style_flags & FT_STYLE_FLAG_BOLD)) {
|
|
Packit |
5e46da |
FT_GlyphSlot_Embolden( face->glyph );
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (style->font_style.italic && !(face->style_flags & FT_STYLE_FLAG_ITALIC)) {
|
|
Packit |
5e46da |
FT_GlyphSlot_Oblique( face->glyph );
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bmp) {
|
|
Packit |
5e46da |
for (jj = 0; jj < face->glyph->bitmap.rows; jj++) {
|
|
Packit |
5e46da |
for (kk = 0; kk < face->glyph->bitmap.width; kk++) {
|
|
Packit |
5e46da |
uint8_t pixel = face->glyph->bitmap.buffer[jj * face->glyph->bitmap.pitch + kk];
|
|
Packit |
5e46da |
if (pixel & 0x80) {
|
|
Packit |
5e46da |
int xpos = x + face->glyph->bitmap_left + kk;
|
|
Packit |
5e46da |
int ypos = y - face->glyph->bitmap_top + jj;
|
|
Packit |
5e46da |
if (xpos >= 0 && xpos < bmp->width && ypos >= 0 && ypos < bmp->height) {
|
|
Packit |
5e46da |
bmp->mem[xpos + ypos * bmp->stride] = color;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* track max baseline when calculating line size */
|
|
Packit |
5e46da |
if (baseline_pos) {
|
|
Packit |
5e46da |
*baseline_pos = BD_MAX(*baseline_pos, (face->size->metrics.ascender >> 6) + 1);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
x += face->glyph->metrics.horiAdvance >> 6;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return x;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void _update_face(TEXTST_RENDER *p, FT_Face *face, const BD_TEXTST_REGION_STYLE *style)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (style->font_id_ref >= p->font_count || !p->font[style->font_id_ref].face) {
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_Render: incorrect font index %d\n", style->font_id_ref);
|
|
Packit |
5e46da |
if (!*face) {
|
|
Packit |
5e46da |
*face = p->font[0].face;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
*face = p->font[style->font_id_ref].face;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
FT_Set_Char_Size(*face, 0, style->font_size << 6, 0, 0);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int _render_line(TEXTST_RENDER *p, TEXTST_BITMAP *bmp,
|
|
Packit |
5e46da |
const BD_TEXTST_REGION_STYLE *base_style,
|
|
Packit |
5e46da |
BD_TEXTST_REGION_STYLE *style,
|
|
Packit |
5e46da |
uint8_t **p_ptr, int *p_elem_count,
|
|
Packit |
5e46da |
int xpos, int ypos, int *baseline_pos)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
FT_Face face = NULL;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* select font */
|
|
Packit |
5e46da |
_update_face(p, &face, style);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
while ( (*p_elem_count) > 0) {
|
|
Packit |
5e46da |
BD_TEXTST_DATA *elem = (BD_TEXTST_DATA*)*p_ptr;
|
|
Packit |
5e46da |
(*p_ptr) += sizeof(BD_TEXTST_DATA);
|
|
Packit |
5e46da |
(*p_elem_count)--;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
switch (elem->type) {
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_STRING:
|
|
Packit |
5e46da |
xpos = _draw_string(face, elem->data.text.string, elem->data.text.length,
|
|
Packit |
5e46da |
bmp, xpos, ypos, style, baseline_pos);
|
|
Packit |
5e46da |
(*p_ptr) += elem->data.text.length;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_NEWLINE:
|
|
Packit |
5e46da |
return xpos;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_FONT_ID:
|
|
Packit |
5e46da |
style->font_id_ref = elem->data.font_id_ref;
|
|
Packit |
5e46da |
_update_face(p, &face, style);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_FONT_STYLE:
|
|
Packit |
5e46da |
style->font_style = elem->data.style.style;
|
|
Packit |
5e46da |
style->outline_color = elem->data.style.outline_color;
|
|
Packit |
5e46da |
style->outline_thickness = elem->data.style.outline_thickness;
|
|
Packit |
5e46da |
if (style->font_style.outline_border) {
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: unsupported style: outline\n");
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_FONT_SIZE:
|
|
Packit |
5e46da |
style->font_size = elem->data.font_size;
|
|
Packit |
5e46da |
_update_face(p, &face, style);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_FONT_COLOR:
|
|
Packit |
5e46da |
style->font_color = elem->data.font_color;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case BD_TEXTST_DATA_RESET_STYLE:
|
|
Packit |
5e46da |
memcpy(style, base_style, sizeof(*style));
|
|
Packit |
5e46da |
_update_face(p, &face, style);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
TEXTST_ERROR("Unknown control code %d\n", elem->type);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return xpos;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#endif /* HAVE_FT2 */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
int textst_render(TEXTST_RENDER *p,
|
|
Packit |
5e46da |
TEXTST_BITMAP *bmp,
|
|
Packit |
5e46da |
const BD_TEXTST_REGION_STYLE *base_style,
|
|
Packit |
5e46da |
const BD_TEXTST_DIALOG_REGION *region)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
#ifdef HAVE_FT2
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* fonts loaded ? */
|
|
Packit |
5e46da |
if (p->font_count < 1) {
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: no fonts loaded\n");
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* TODO: */
|
|
Packit |
5e46da |
if (base_style->text_flow != BD_TEXTST_FLOW_LEFT_RIGHT) {
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: unsupported text flow type %d\n", base_style->text_flow);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (bmp->argb) {
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: ARGB output not implemented\n");
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (base_style->font_style.outline_border) {
|
|
Packit |
5e46da |
/* TODO: styles: see ex. vlc/modules/text_renderer/freetype.c ; function GetGlyph() */
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: unsupported style: outline\n");
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
BD_TEXTST_REGION_STYLE s; /* current style settings */
|
|
Packit |
5e46da |
unsigned line;
|
|
Packit |
5e46da |
uint8_t *ptr = (uint8_t*)region->elem;
|
|
Packit |
5e46da |
int elem_count = region->elem_count;
|
|
Packit |
5e46da |
int xpos = 0;
|
|
Packit |
5e46da |
int ypos = 0;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* settings can be changed and reset with inline codes. Use local copy. */
|
|
Packit |
5e46da |
memcpy(&s, base_style, sizeof(s));
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* apply vertical alignment */
|
|
Packit |
5e46da |
switch (s.text_valign) {
|
|
Packit |
5e46da |
case BD_TEXTST_VALIGN_TOP:
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case BD_TEXTST_VALIGN_BOTTOM:
|
|
Packit |
5e46da |
ypos = s.text_box.height - region->line_count * s.line_space;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case BD_TEXTST_VALIGN_MIDDLE:
|
|
Packit |
5e46da |
ypos = (s.text_box.height - region->line_count * s.line_space) / 2;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: unsupported vertical align %d\n", s.text_halign);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
for (line = 0; line < region->line_count; line++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* calculate line width and max. ascender */
|
|
Packit |
5e46da |
uint8_t *ptr_tmp = ptr;
|
|
Packit |
5e46da |
int elem_count_tmp = elem_count;
|
|
Packit |
5e46da |
BD_TEXTST_REGION_STYLE style_tmp;
|
|
Packit |
5e46da |
int baseline = 0, line_width;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* dry-run: count line width and height */
|
|
Packit |
5e46da |
memcpy(&style_tmp, &s, sizeof(s)); /* use copy in first pass */
|
|
Packit |
5e46da |
line_width = _render_line(p, NULL, base_style, &style_tmp, &ptr_tmp, &elem_count_tmp, 0, 0, &baseline);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* adjust to baseline */
|
|
Packit |
5e46da |
ypos += baseline;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* apply horizontal alignment */
|
|
Packit |
5e46da |
xpos = 0;
|
|
Packit |
5e46da |
switch (s.text_halign) {
|
|
Packit |
5e46da |
case BD_TEXTST_HALIGN_LEFT:
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case BD_TEXTST_HALIGN_RIGHT:
|
|
Packit |
5e46da |
xpos = s.text_box.width - line_width - 1;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case BD_TEXTST_HALIGN_CENTER:
|
|
Packit |
5e46da |
xpos = (s.text_box.width - line_width) / 2 - 1;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
TEXTST_ERROR("textst_render: unsupported horizontal align %d\n", s.text_halign);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* render line */
|
|
Packit |
5e46da |
_render_line(p, bmp, base_style, &s, &ptr, &elem_count, xpos, ypos, NULL);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
ypos += s.line_space - baseline;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#else
|
|
Packit |
5e46da |
(void)p;
|
|
Packit |
5e46da |
(void)bmp;
|
|
Packit |
5e46da |
(void)base_style;
|
|
Packit |
5e46da |
(void)region;
|
|
Packit |
5e46da |
#endif /* HAVE_FT2 */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|