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