/* 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 (); }