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#ifndef MINIKIN_FONT_H
18bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien#define MINIKIN_FONT_H
19bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
205986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod#include <string>
215986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod
22b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien#include <minikin/MinikinRefCounted.h>
239a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien#include <minikin/FontFamily.h>
24b80c1f19c58b927820a8a24bf2218e5645724608Raph Levien
25bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien// An abstraction for platform fonts, allowing Minikin to be used with
26bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien// multiple actual implementations of fonts.
27bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
28bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Leviennamespace android {
29bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
30d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien// The hyphen edit represents an edit to the string when a word is
31d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien// hyphenated. The most common hyphen edit is adding a "-" at the end
32d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien// of a syllable, but nonstandard hyphenation allows for more choices.
33d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levienclass HyphenEdit {
34d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levienpublic:
35d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien    HyphenEdit() : hyphen(0) { }
36d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien    HyphenEdit(uint32_t hyphenInt) : hyphen(hyphenInt) { }
37d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien    bool hasHyphen() const { return hyphen != 0; }
386c4d167bff33c24c239d77ddb1044b18d180766aRaph Levien    bool operator==(const HyphenEdit &other) const { return hyphen == other.hyphen; }
39d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levienprivate:
40d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien    uint32_t hyphen;
41d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien};
42d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien
43bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levienclass MinikinFont;
44bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
45bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien// Possibly move into own .h file?
465986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod// Note: if you add a field here, either add it to LayoutCacheKey or to skipCache()
47bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levienstruct MinikinPaint {
4883d5a3c53d77c34fbeac7012ab3612933982d494Behdad Esfahbod    MinikinPaint() : font(0), size(0), scaleX(0), skewX(0), letterSpacing(0), paintFlags(0),
495986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod            fakery(), fontFeatureSettings() { }
505986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod
515986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod    bool skipCache() const {
526c4d167bff33c24c239d77ddb1044b18d180766aRaph Levien        return !fontFeatureSettings.empty();
535986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod    }
545986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod
55bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    MinikinFont *font;
56bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    float size;
57448b0fd720d7ba902b9be224a287d08abe3ebea8Raph Levien    float scaleX;
58448b0fd720d7ba902b9be224a287d08abe3ebea8Raph Levien    float skewX;
598e7a3dae37e9a22b2c054aec852615843d71caf6Behdad Esfahbod    float letterSpacing;
603164d1a77eecf3185347a44342131f4275de824fRaph Levien    uint32_t paintFlags;
619a5f713add8cfb91ac2c9ed5c917309053201ab6Raph Levien    FontFakery fakery;
62d692d6a9791145d41d7778cdf6b40b20c2be8cb4Raph Levien    HyphenEdit hyphenEdit;
635986f6048ae21e0ec094c1f2ca0169d0ca6ec6b5Behdad Esfahbod    std::string fontFeatureSettings;
64bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien};
65bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
666740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levien// Only a few flags affect layout, but those that do should have values
676740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levien// consistent with Android's paint flags.
686740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levienenum MinikinPaintFlags {
696740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levien    LinearTextFlag = 0x40,
706740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levien};
716740536e3927d25bf5c2567e5f6e8c175973cbb7Raph Levien
72ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levienstruct MinikinRect {
73ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    float mLeft, mTop, mRight, mBottom;
74ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    bool isEmpty() const {
75ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        return mLeft == mRight || mTop == mBottom;
76ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    }
77ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    void set(const MinikinRect& r) {
78ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mLeft = r.mLeft;
79ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mTop = r.mTop;
80ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mRight = r.mRight;
81ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mBottom = r.mBottom;
82ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    }
83ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    void offset(float dx, float dy) {
84ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mLeft += dx;
85ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mTop += dy;
86ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mRight += dx;
87ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mBottom += dy;
88ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    }
89ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    void setEmpty() {
90ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        mLeft = mTop = mRight = mBottom = 0;
91ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    }
92ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    void join(const MinikinRect& r);
93ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien};
94ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien
95bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levienclass MinikinFontFreeType;
96bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
97aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien// Callback for freeing data
98aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levientypedef void (*MinikinDestroyFunc) (void* data);
99aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien
100b80c1f19c58b927820a8a24bf2218e5645724608Raph Levienclass MinikinFont : public MinikinRefCounted {
101bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levienpublic:
1026c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    MinikinFont(int32_t uniqueId) : mUniqueId(uniqueId) {}
1036c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka
1049afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien    virtual ~MinikinFont();
1059afcc6e2bd4d89e4e1deb6e18c3c4daca4e114fdRaph Levien
106bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    virtual float GetHorizontalAdvance(uint32_t glyph_id,
107bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien        const MinikinPaint &paint) const = 0;
108bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
109ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien    virtual void GetBounds(MinikinRect* bounds, uint32_t glyph_id,
110ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien        const MinikinPaint &paint) const = 0;
111ecc2d34ac23a497988f21e5f415b53c007b9d8c5Raph Levien
112aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    virtual const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) = 0;
113aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien
114aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    // Override if font can provide access to raw data
115aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    virtual const void* GetFontData() const {
116aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien        return nullptr;
117aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    }
118aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien
119aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    // Override if font can provide access to raw data
120aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    virtual size_t GetFontSize() const {
121aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien        return 0;
122aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    }
123aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien
124aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    // Override if font can provide access to raw data.
125aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    // Returns index within OpenType collection
126aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    virtual int GetFontIndex() const {
127aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien        return 0;
128aaa4e3470270496e6eb80704eadecb2cb7c56bf0Raph Levien    }
129bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
130bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    static uint32_t MakeTag(char c1, char c2, char c3, char c4) {
131bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien        return ((uint32_t)c1 << 24) | ((uint32_t)c2 << 16) |
132bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien            ((uint32_t)c3 << 8) | (uint32_t)c4;
133bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien    }
1346c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka
1356c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    int32_t GetUniqueId() const { return mUniqueId; }
1366c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonakaprivate:
1376c60831cfce24b0749f50f37231e0a56d8fd4b85Seigo Nonaka    const int32_t mUniqueId;
138bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien};
139bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
140bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien}  // namespace android
141bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien
142bcc3dc5a2591a95a57e379e27cbad69c18e91e67Raph Levien#endif  // MINIKIN_FONT_H
143