Home | History | Annotate | Download | only in minikin
      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 <memory>
     23 #include <vector>
     24 
     25 #include <minikin/FontCollection.h>
     26 
     27 namespace minikin {
     28 
     29 struct LayoutGlyph {
     30     // index into mFaces and mHbFonts vectors. We could imagine
     31     // moving this into a run length representation, because it's
     32     // more efficient for long strings, and we'll probably need
     33     // something like that for paint attributes (color, underline,
     34     // fake b/i, etc), as having those per-glyph is bloated.
     35     int font_ix;
     36 
     37     unsigned int glyph_id;
     38     float x;
     39     float y;
     40 };
     41 
     42 // Internal state used during layout operation
     43 struct LayoutContext;
     44 
     45 enum {
     46     kBidi_LTR = 0,
     47     kBidi_RTL = 1,
     48     kBidi_Default_LTR = 2,
     49     kBidi_Default_RTL = 3,
     50     kBidi_Force_LTR = 4,
     51     kBidi_Force_RTL = 5,
     52 
     53     kBidi_Mask = 0x7
     54 };
     55 
     56 // Lifecycle and threading assumptions for Layout:
     57 // The object is assumed to be owned by a single thread; multiple threads
     58 // may not mutate it at the same time.
     59 class Layout {
     60 public:
     61 
     62     Layout() : mGlyphs(), mAdvances(), mFaces(), mAdvance(0), mBounds() {
     63         mBounds.setEmpty();
     64     }
     65 
     66     Layout(Layout&& layout) = default;
     67 
     68     // Forbid copying and assignment.
     69     Layout(const Layout&) = delete;
     70     void operator=(const Layout&) = delete;
     71 
     72     void dump() const;
     73 
     74     void doLayout(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
     75         int bidiFlags, const FontStyle &style, const MinikinPaint &paint,
     76         const std::shared_ptr<FontCollection>& collection);
     77 
     78     static float measureText(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
     79         int bidiFlags, const FontStyle &style, const MinikinPaint &paint,
     80         const std::shared_ptr<FontCollection>& collection, float* advances);
     81 
     82     // public accessors
     83     size_t nGlyphs() const;
     84     const MinikinFont* getFont(int i) const;
     85     FontFakery getFakery(int i) const;
     86     unsigned int getGlyphId(int i) const;
     87     float getX(int i) const;
     88     float getY(int i) const;
     89 
     90     float getAdvance() const;
     91 
     92     // Get advances, copying into caller-provided buffer. The size of this
     93     // buffer must match the length of the string (count arg to doLayout).
     94     void getAdvances(float* advances);
     95 
     96     // The i parameter is an offset within the buf relative to start, it is < count, where
     97     // start and count are the parameters to doLayout
     98     float getCharAdvance(size_t i) const { return mAdvances[i]; }
     99 
    100     void getBounds(MinikinRect* rect) const;
    101 
    102     // Purge all caches, useful in low memory conditions
    103     static void purgeCaches();
    104 
    105 private:
    106     friend class LayoutCacheKey;
    107 
    108     // Find a face in the mFaces vector, or create a new entry
    109     int findFace(const FakedFont& face, LayoutContext* ctx);
    110 
    111     // Clears layout, ready to be used again
    112     void reset();
    113 
    114     // Lay out a single bidi run
    115     // When layout is not null, layout info will be stored in the object.
    116     // When advances is not null, measurement results will be stored in the array.
    117     static float doLayoutRunCached(const uint16_t* buf, size_t runStart, size_t runLength,
    118         size_t bufSize, bool isRtl, LayoutContext* ctx, size_t dstStart,
    119         const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances);
    120 
    121     // Lay out a single word
    122     static float doLayoutWord(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
    123         bool isRtl, LayoutContext* ctx, size_t bufStart,
    124         const std::shared_ptr<FontCollection>& collection, Layout* layout, float* advances);
    125 
    126     // Lay out a single bidi run
    127     void doLayoutRun(const uint16_t* buf, size_t start, size_t count, size_t bufSize,
    128         bool isRtl, LayoutContext* ctx, const std::shared_ptr<FontCollection>& collection);
    129 
    130     // Append another layout (for example, cached value) into this one
    131     void appendLayout(Layout* src, size_t start, float extraAdvance);
    132 
    133     std::vector<LayoutGlyph> mGlyphs;
    134     std::vector<float> mAdvances;
    135 
    136     std::vector<FakedFont> mFaces;
    137     float mAdvance;
    138     MinikinRect mBounds;
    139 };
    140 
    141 }  // namespace minikin
    142 
    143 #endif  // MINIKIN_LAYOUT_H
    144