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    mTypeface(typeface) {
34    mUniqueId = sIdCounter++;
35}
36
37MinikinFontFreeType::~MinikinFontFreeType() {
38    FT_Done_Face(mTypeface);
39}
40
41bool MinikinFontFreeType::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
42    FT_UInt glyph_index = FT_Get_Char_Index(mTypeface, codepoint);
43    *glyph = glyph_index;
44    return !!glyph_index;
45}
46
47float MinikinFontFreeType::GetHorizontalAdvance(uint32_t glyph_id,
48    const MinikinPaint &paint) const {
49    FT_Set_Pixel_Sizes(mTypeface, 0, paint.size);
50	FT_UInt32 flags = FT_LOAD_DEFAULT;  // TODO: respect hinting settings
51	FT_Fixed advance;
52    FT_Error error = FT_Get_Advance(mTypeface, glyph_id, flags, &advance);
53    return advance * (1.0 / 65536);
54}
55
56void MinikinFontFreeType::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
57    const MinikinPaint& paint) const {
58    // TODO: NYI
59}
60
61bool MinikinFontFreeType::GetTable(uint32_t tag, uint8_t *buf, size_t *size) {
62	FT_ULong ftsize = *size;
63	FT_Error error = FT_Load_Sfnt_Table(mTypeface, tag, 0, buf, &ftsize);
64	if (error != 0) {
65		return false;
66	}
67	*size = ftsize;
68	return true;
69}
70
71int32_t MinikinFontFreeType::GetUniqueId() const {
72	return mUniqueId;
73}
74
75bool MinikinFontFreeType::Render(uint32_t glyph_id,
76    const MinikinPaint &paint, 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