/* FreeType font driver for Haiku
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see . */
#include
#include "haiku_support.h"
#include
#include
#include
#include
#include
#include
#include
#include FT_FREETYPE_H
#include FT_SIZES_H
#include FT_BITMAP_H
#define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
static void
render_g8 (FT_Bitmap *bitmap, uint32_t color, int dx, int dy, BBitmap *bm,
int max_x, int max_y)
{
if (!bitmap->width || !bitmap->rows)
return;
for (int y = 0; y < bitmap->rows; ++y)
{
if (y + dy >= max_y)
continue;
uint8_t *row_start_glyph =
(uint8_t *) &bitmap->buffer[y * bitmap->pitch];
uint32_t *row_start_bitmap = ((uint32_t *) bm->Bits ()) +
(y + dy) * bm->BytesPerRow () / 4;
for (int x = 0; x < bitmap->width; ++x)
{
if (x + dx > max_x)
continue;
row_start_bitmap[x + dx] =
ARGB_TO_ULONG (std::lrint ((double) row_start_glyph[x] /
(double) bitmap->num_grays * 255),
RED_FROM_ULONG (color),
GREEN_FROM_ULONG (color),
BLUE_FROM_ULONG (color));
}
}
}
extern void
BView_FT_render_glyphs (FT_Face face, unsigned int *codes,
int len, uint32_t color, int x, int y,
void *view, int width, int height,
int sx, int sy)
{
FT_Error error = FT_Err_Ok;
BView *vw = (BView *) view;
static BBitmap *canvas = NULL;
int view_width, view_height;
view_width = vw->Bounds ().Width ();
view_height = vw->Bounds ().Height ();
int ix = x, iy = y;
if (canvas && (canvas->Bounds () != vw->Bounds ()))
{
delete canvas;
canvas = NULL;
}
if (!canvas)
canvas = new BBitmap (vw->Bounds (), B_RGBA32);
vw->PushState ();
vw->SetDrawingMode (B_OP_OVER);
memset (canvas->Bits (), 0, canvas->BitsLength ());
for (int i = 0; i < len; ++i)
{
error = FT_Load_Glyph (face, codes[i], FT_LOAD_DEFAULT);
if (error != FT_Err_Ok)
continue;
if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
{
error = FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL);
if (error)
{
x += face->glyph->advance.x >> 6;
y += face->glyph->advance.y >> 6;
continue;
}
render_g8 (&face->glyph->bitmap, color,
x + face->glyph->bitmap_left,
y - face->glyph->bitmap_top,
canvas, view_width, view_height);
}
x += face->glyph->advance.x >> 6;
y += face->glyph->advance.y >> 6;
}
vw->DrawBitmap (canvas);
vw->PopState ();
vw->Sync ();
}