1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Implementation of MinikinFont abstraction specialized for FreeType
18
19#include <stdint.h>
20
21#include <ft2build.h>
22#include FT_FREETYPE_H
23#include FT_TRUETYPE_TABLES_H
24#include FT_ADVANCES_H
25
26#include <minikin/MinikinFontFreeType.h>
27
28namespace android {
29
30int32_t MinikinFontFreeType::sIdCounter = 0;
31
32MinikinFontFreeType::MinikinFontFreeType(FT_Face typeface) :
33    MinikinFont(sIdCounter++),
34    mTypeface(typeface) {
35}
36
37MinikinFontFreeType::~MinikinFontFreeType() {
38    FT_Done_Face(mTypeface);
39}
40
41float MinikinFontFreeType::GetHorizontalAdvance(uint32_t glyph_id,
42    const MinikinPaint &paint) const {
43    FT_Set_Pixel_Sizes(mTypeface, 0, paint.size);
44    FT_UInt32 flags = FT_LOAD_DEFAULT;  // TODO: respect hinting settings
45    FT_Fixed advance;
46    FT_Get_Advance(mTypeface, glyph_id, flags, &advance);
47    return advance * (1.0 / 65536);
48}
49
50void MinikinFontFreeType::GetBounds(MinikinRect* /* bounds */, uint32_t /* glyph_id*/,
51        const MinikinPaint& /* paint */) const {
52    // TODO: NYI
53}
54
55const void* MinikinFontFreeType::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) {
56    FT_ULong ftsize = 0;
57    FT_Error error = FT_Load_Sfnt_Table(mTypeface, tag, 0, nullptr, &ftsize);
58    if (error != 0) {
59        return nullptr;
60    }
61    FT_Byte* buf = reinterpret_cast<FT_Byte*>(malloc(ftsize));
62    if (buf == nullptr) {
63        return nullptr;
64    }
65    error = FT_Load_Sfnt_Table(mTypeface, tag, 0, buf, &ftsize);
66    if (error != 0) {
67        free(buf);
68        return nullptr;
69    }
70    *destroy = free;
71    *size = ftsize;
72    return buf;
73}
74
75bool MinikinFontFreeType::Render(uint32_t glyph_id, const MinikinPaint& /* paint */,
76        GlyphBitmap *result) {
77    FT_Error error;
78    FT_Int32 load_flags = FT_LOAD_DEFAULT;  // TODO: respect hinting settings
79    error = FT_Load_Glyph(mTypeface, glyph_id, load_flags);
80    if (error != 0) {
81        return false;
82    }
83    error = FT_Render_Glyph(mTypeface->glyph, FT_RENDER_MODE_NORMAL);
84    if (error != 0) {
85        return false;
86    }
87    FT_Bitmap &bitmap = mTypeface->glyph->bitmap;
88    result->buffer = bitmap.buffer;
89    result->width = bitmap.width;
90    result->height = bitmap.rows;
91    result->left = mTypeface->glyph->bitmap_left;
92    result->top = mTypeface->glyph->bitmap_top;
93    return true;
94}
95
96MinikinFontFreeType* MinikinFontFreeType::GetFreeType() {
97    return this;
98}
99
100}  // namespace android
101