2 #include "glyph_cache.h"
3 #include "gdipp_lib/scoped_rw_lock.h"
4 #include "gdipp_server/global.h"
9 glyph_cache::string_id_type
glyph_cache::get_string_id(const wchar_t *string
, unsigned int count
, bool is_glyph_index
)
11 string_id_type string_id
;
13 MurmurHash3_x64_128(string
, count
* sizeof(wchar_t), is_glyph_index
, &string_id
);
15 MurmurHash3_x86_128(string
, count
* sizeof(wchar_t), is_glyph_index
, &string_id
);
21 glyph_cache::char_id_type
glyph_cache::get_char_id(uint128_t render_trait
, FT_UInt index
, bool is_glyph_index
)
25 * low 64 bits: low 64 bits of render_trait
29 | render_trait (65 - 96 bit) | is_glyph_index | index |
31 char_id_type char_id
= render_trait
;
32 char_id
.second
= (char_id
.second
<< 33) | (static_cast<uint64_t>(is_glyph_index
) << 32) | index
;
36 glyph_cache::~glyph_cache()
38 for (std::map
<char_id_type
, INIT_ONCE
>::iterator glyph_iter
= _glyph_store
.begin(); glyph_iter
!= _glyph_store
.end(); ++glyph_iter
)
42 InitOnceBeginInitialize(&glyph_iter
->second
, INIT_ONCE_CHECK_ONLY
, &pending
, reinterpret_cast<void **>(&glyph
));
47 for (std::map
<string_id_type
, trait_to_run_map
>::iterator str_iter
= _glyph_run_store
.begin(); str_iter
!= _glyph_run_store
.end(); ++str_iter
)
48 erase_glyph_run_cache_string(str_iter
);
51 void glyph_cache::initialize()
53 _glyph_run_lru
.resize(min(1 << server_cache_size
, 16777216));
56 const FT_Glyph
glyph_cache::lookup_glyph(char_id_type char_id
)
58 std::map
<char_id_type
, INIT_ONCE
>::iterator glyph_iter
;
61 const scoped_rw_lock
lock_w(scoped_rw_lock::SERVER_GLYPH_CACHE
, false);
63 glyph_iter
= _glyph_store
.find(char_id
);
64 if (glyph_iter
== _glyph_store
.end())
66 const std::pair
<std::map
<char_id_type
, INIT_ONCE
>::iterator
, bool> insert_ret
= _glyph_store
.insert(std::pair
<char_id_type
, INIT_ONCE
>(char_id
, INIT_ONCE()));
67 assert(insert_ret
.second
);
68 glyph_iter
= insert_ret
.first
;
69 InitOnceInitialize(&glyph_iter
->second
);
73 FT_Glyph glyph
= NULL
;
75 InitOnceBeginInitialize(&glyph_iter
->second
, 0, &pending
, reinterpret_cast<void **>(&glyph
));
76 assert((glyph
== NULL
) == pending
);
81 bool glyph_cache::store_glyph(char_id_type char_id
, const FT_Glyph glyph
)
83 std::map
<char_id_type
, INIT_ONCE
>::iterator glyph_iter
;
86 const scoped_rw_lock
lock_w(scoped_rw_lock::SERVER_GLYPH_CACHE
, false);
88 glyph_iter
= _glyph_store
.find(char_id
);
91 InitOnceComplete(&glyph_iter
->second
, (glyph
== NULL
? INIT_ONCE_INIT_FAILED
: 0), glyph
);
95 const glyph_run
*glyph_cache::lookup_glyph_run(string_id_type string_id
, uint128_t render_trait
)
97 trait_to_run_map::iterator trait_iter
;
100 const scoped_rw_lock
lock_w(scoped_rw_lock::SERVER_GLYPH_RUN_CACHE
, false);
102 std::map
<uint128_t
, trait_to_run_map
>::iterator str_iter
= _glyph_run_store
.find(string_id
);
103 if (str_iter
== _glyph_run_store
.end())
105 const std::pair
<std::map
<string_id_type
, trait_to_run_map
>::iterator
, bool> str_insert_ret
= _glyph_run_store
.insert(std::pair
<string_id_type
, trait_to_run_map
>(string_id
, trait_to_run_map()));
106 assert(str_insert_ret
.second
);
107 str_iter
= str_insert_ret
.first
;
108 trait_iter
= str_iter
->second
.end();
112 trait_iter
= str_iter
->second
.find(render_trait
);
115 if (trait_iter
== str_iter
->second
.end())
117 const std::pair
<trait_to_run_map::iterator
, bool> trait_insert_ret
= str_iter
->second
.insert(std::pair
<uint128_t
, INIT_ONCE
>(render_trait
, INIT_ONCE()));
118 assert(trait_insert_ret
.second
);
119 trait_iter
= trait_insert_ret
.first
;
120 InitOnceInitialize(&trait_iter
->second
);
124 glyph_run
*a_glyph_run
= NULL
;
126 InitOnceBeginInitialize(&trait_iter
->second
, 0, &pending
, reinterpret_cast<void **>(&a_glyph_run
));
127 assert((a_glyph_run
== NULL
) == pending
);
132 bool glyph_cache::store_glyph_run(string_id_type string_id
, uint128_t render_trait
, glyph_run
*a_glyph_run
)
134 trait_to_run_map::iterator trait_iter
;
138 string_id_type erased_str
;
139 std::map
<string_id_type
, trait_to_run_map
>::iterator str_iter
;
141 const scoped_rw_lock
lock_w(scoped_rw_lock::SERVER_GLYPH_RUN_CACHE
, false);
143 b_ret
= _glyph_run_lru
.access(string_id
, &erased_str
);
146 // the string is evicted from LRU cache
147 // erase all cached glyph run that is under the evicted string ID
149 str_iter
= _glyph_run_store
.find(erased_str
);
150 assert(str_iter
!= _glyph_run_store
.end());
151 erase_glyph_run_cache_string(str_iter
);
152 _glyph_run_store
.erase(str_iter
);
155 str_iter
= _glyph_run_store
.find(string_id
);
156 assert(str_iter
!= _glyph_run_store
.end());
157 trait_iter
= str_iter
->second
.find(render_trait
);
160 InitOnceComplete(&trait_iter
->second
, (a_glyph_run
== NULL
? INIT_ONCE_INIT_FAILED
: 0), a_glyph_run
);
161 return a_glyph_run
!= NULL
;
164 void glyph_cache::erase_glyph_run_cache_string(std::map
<string_id_type
, trait_to_run_map
>::iterator str_iter
)
166 for (trait_to_run_map::iterator trait_iter
= str_iter
->second
.begin(); trait_iter
!= str_iter
->second
.end(); ++trait_iter
)
169 glyph_run
*a_glyph_run
;
170 InitOnceBeginInitialize(&trait_iter
->second
, INIT_ONCE_CHECK_ONLY
, &pending
, reinterpret_cast<void **>(&a_glyph_run
));