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 #ifndef MINIKIN_LAYOUT_H
18 #define MINIKIN_LAYOUT_H
19 
20 #include <hb.h>
21 
22 #include <vector>
23 
24 #include <minikin/FontCollection.h>
25 #include <minikin/MinikinFontFreeType.h>
26 
27 namespace minikin {
28 
29 // The Bitmap class is for debugging. We'll probably move it out
30 // of here into a separate lightweight software rendering module
31 // (optional, as we'd hope most clients would do their own)
32 class Bitmap {
33 public:
34     Bitmap(int width, int height);
35     ~Bitmap();
36     void writePnm(std::ofstream& o) const;
37     void drawGlyph(const android::GlyphBitmap& bitmap, int x, int y);
38 private:
39     int width;
40     int height;
41     uint8_t* buf;
42 };
43 
44 } // namespace minikin
45 
46 namespace android {
47 
48 struct LayoutGlyph {
49     // index into mFaces and mHbFonts vectors. We could imagine
50     // moving this into a run length representation, because it's
51     // more efficient for long strings, and we'll probably need
52     // something like that for paint attributes (color, underline,
53     // fake b/i, etc), as having those per-glyph is bloated.
54     int font_ix;
55 
56     unsigned int glyph_id;
57     float x;
58     float y;
59 };
60 
61 // Internal state used during layout operation
62 struct LayoutContext;
63 
64 enum {
65     kBidi_LTR = 0,
66     kBidi_RTL = 1,
67     kBidi_Default_LTR = 2,
68     kBidi_Default_RTL = 3,
69     kBidi_Force_LTR = 4,
70     kBidi_Force_RTL = 5,
71 
72     kBidi_Mask = 0x7
73 };
74 
75 // Lifecycle and threading assumptions for Layout:
76 // The object is assumed to be owned by a single thread; multiple threads
77 // may not mutate it at the same time.
78 // The lifetime of the FontCollection set through setFontCollection must
79 // extend through the lifetime of the Layout object.
80 class Layout {
81 public:
82 
Layout()83     Layout() : mGlyphs(), mAdvances(), mCollection(0), mFaces(), mAdvance(0), mBounds() {
84         mBounds.setEmpty();
85     }
86 
87     // Clears layout, ready to be used again
88     void reset();
89 
90     void dump() const;
91     void setFontCollection(const FontCollection* collection);
92 
93     void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
94         int bidiFlags, const FontStyle &style, const MinikinPaint &paint);
95 
96     static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
97         int bidiFlags, const FontStyle &style, const MinikinPaint &paint,
98         const FontCollection* collection, float* advances);
99 
100     void draw(minikin::Bitmap*, int x0, int y0, float size) const;
101 
102     // Deprecated. Nont needed. Remove when callers are removed.
103     static void init();
104 
105     // public accessors
106     size_t nGlyphs() const;
107     // Does not bump reference; ownership is still layout
108     MinikinFont *getFont(int i) const;
109     FontFakery getFakery(int i) const;
110     unsigned int getGlyphId(int i) const;
111     float getX(int i) const;
112     float getY(int i) const;
113 
114     float getAdvance() const;
115 
116     // Get advances, copying into caller-provided buffer. The size of this
117     // buffer must match the length of the string (count arg to doLayout).
118     void getAdvances(float* advances);
119 
120     // The i parameter is an offset within the buf relative to start, it is < count, where
121     // start and count are the parameters to doLayout
getCharAdvance(size_t i)122     float getCharAdvance(size_t i) const { return mAdvances[i]; }
123 
124     void getBounds(MinikinRect* rect);
125 
126     // Purge all caches, useful in low memory conditions
127     static void purgeCaches();
128 
129 private:
130     friend class LayoutCacheKey;
131 
132     // Find a face in the mFaces vector, or create a new entry
133     int findFace(FakedFont face, LayoutContext* ctx);
134 
135     // Lay out a single bidi run
136     // When layout is not null, layout info will be stored in the object.
137     // When advances is not null, measurement results will be stored in the array.
138     static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength,
139         size_t bufSize, bool isRtl, LayoutContext* ctx, size_t dstStart,
140         const FontCollection* collection, Layout* layout, float* advances);
141 
142     // Lay out a single word
143     static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
144         bool isRtl, LayoutContext* ctx, size_t bufStart, const FontCollection* collection,
145         Layout* layout, float* advances);
146 
147     // Lay out a single bidi run
148     void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
149         bool isRtl, LayoutContext* ctx);
150 
151     // Append another layout (for example, cached value) into this one
152     void appendLayout(Layout* src, size_t start);
153 
154     std::vector<LayoutGlyph> mGlyphs;
155     std::vector<float> mAdvances;
156 
157     const FontCollection* mCollection;
158     std::vector<FakedFont> mFaces;
159     float mAdvance;
160     MinikinRect mBounds;
161 };
162 
163 }  // namespace android
164 
165 #endif  // MINIKIN_LAYOUT_H
166