183 glyphFormat = -1; |
183 glyphFormat = -1; |
184 } |
184 } |
185 |
185 |
186 QFontEngine::~QFontEngine() |
186 QFontEngine::~QFontEngine() |
187 { |
187 { |
188 for (GlyphPointerHash::const_iterator it = m_glyphPointerHash.constBegin(), |
188 for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), |
189 end = m_glyphPointerHash.constEnd(); it != end; ++it) { |
189 end = m_glyphCaches.constEnd(); it != end; ++it) { |
190 for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(), |
190 delete it->cache; |
191 end2 = it.value().constEnd(); it2 != end2; ++it2) { |
191 } |
192 delete *it2; |
192 m_glyphCaches.clear(); |
193 } |
|
194 } |
|
195 m_glyphPointerHash.clear(); |
|
196 for (GlyphIntHash::const_iterator it = m_glyphIntHash.constBegin(), |
|
197 end = m_glyphIntHash.constEnd(); it != end; ++it) { |
|
198 for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(), |
|
199 end2 = it.value().constEnd(); it2 != end2; ++it2) { |
|
200 delete *it2; |
|
201 } |
|
202 } |
|
203 m_glyphIntHash.clear(); |
|
204 qHBFreeFace(hbFace); |
193 qHBFreeFace(hbFace); |
205 } |
194 } |
206 |
195 |
207 QFixed QFontEngine::lineThickness() const |
196 QFixed QFontEngine::lineThickness() const |
208 { |
197 { |
711 if (!getSfntTableData(tag, reinterpret_cast<uchar *>(table.data()), &len)) |
700 if (!getSfntTableData(tag, reinterpret_cast<uchar *>(table.data()), &len)) |
712 return QByteArray(); |
701 return QByteArray(); |
713 return table; |
702 return table; |
714 } |
703 } |
715 |
704 |
716 void QFontEngine::expireGlyphCache() |
|
717 { |
|
718 if (m_glyphCacheQueue.count() > 10) { // hold only 10 caches in memory. |
|
719 QFontEngineGlyphCache *old = m_glyphCacheQueue.takeFirst(); |
|
720 // remove the value from either of our hashes |
|
721 for (GlyphPointerHash::iterator i = m_glyphPointerHash.begin(); i != m_glyphPointerHash.end(); ++i) { |
|
722 QList<QFontEngineGlyphCache *> list = i.value(); |
|
723 if (list.removeAll(old)) { |
|
724 if (list.isEmpty()) |
|
725 m_glyphPointerHash.remove(i.key()); |
|
726 else |
|
727 m_glyphPointerHash.insert(i.key(), list); |
|
728 break; |
|
729 } |
|
730 } |
|
731 for (GlyphIntHash::iterator i = m_glyphIntHash.begin(); i != m_glyphIntHash.end(); ++i) { |
|
732 QList<QFontEngineGlyphCache *> list = i.value(); |
|
733 if (list.removeAll(old)) { |
|
734 if (list.isEmpty()) |
|
735 m_glyphIntHash.remove(i.key()); |
|
736 else |
|
737 m_glyphIntHash.insert(i.key(), list); |
|
738 break; |
|
739 } |
|
740 } |
|
741 delete old; |
|
742 } |
|
743 } |
|
744 |
|
745 void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) |
705 void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) |
746 { |
706 { |
747 Q_ASSERT(data); |
707 Q_ASSERT(data); |
748 QList<QFontEngineGlyphCache*> items = m_glyphPointerHash.value(key); |
708 |
749 |
709 GlyphCacheEntry entry = { key, data }; |
750 for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) { |
710 if (m_glyphCaches.contains(entry)) |
751 QFontEngineGlyphCache *c = *it; |
711 return; |
752 if (qtransform_equals_no_translate(c->m_transform, data->m_transform)) { |
712 |
753 if (c == data) |
713 // Limit the glyph caches to 4. This covers all 90 degree rotations and limits |
754 return; |
714 // memory use when there is continous or random rotation |
755 items.removeAll(c); |
715 if (m_glyphCaches.size() == 4) |
756 delete c; |
716 delete m_glyphCaches.takeLast().cache; |
757 break; |
717 |
758 } |
718 m_glyphCaches.push_front(entry); |
759 } |
719 |
760 items.append(data); |
720 } |
761 m_glyphPointerHash.insert(key, items); |
721 |
762 |
722 QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const |
763 m_glyphCacheQueue.append(data); |
723 { |
764 expireGlyphCache(); |
724 for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { |
765 } |
725 QFontEngineGlyphCache *c = it->cache; |
766 |
726 if (key == it->context |
767 void QFontEngine::setGlyphCache(QFontEngineGlyphCache::Type key, QFontEngineGlyphCache *data) |
727 && type == c->cacheType() |
768 { |
728 && qtransform_equals_no_translate(c->m_transform, transform)) { |
769 Q_ASSERT(data); |
|
770 QList<QFontEngineGlyphCache*> items = m_glyphIntHash.value(key); |
|
771 |
|
772 for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) { |
|
773 QFontEngineGlyphCache *c = *it; |
|
774 if (qtransform_equals_no_translate(c->m_transform, data->m_transform)) { |
|
775 if (c == data) |
|
776 return; |
|
777 items.removeAll(c); |
|
778 delete c; |
|
779 break; |
|
780 } |
|
781 } |
|
782 items.append(data); |
|
783 m_glyphIntHash.insert(key, items); |
|
784 |
|
785 m_glyphCacheQueue.append(data); |
|
786 expireGlyphCache(); |
|
787 } |
|
788 |
|
789 QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, const QTransform &transform) const |
|
790 { |
|
791 QList<QFontEngineGlyphCache*> items = m_glyphPointerHash.value(key); |
|
792 |
|
793 for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) { |
|
794 QFontEngineGlyphCache *c = *it; |
|
795 if (qtransform_equals_no_translate(c->m_transform, transform)) { |
|
796 m_glyphCacheQueue.removeAll(c); // last used, move it up |
|
797 m_glyphCacheQueue.append(c); |
|
798 return c; |
|
799 } |
|
800 } |
|
801 return 0; |
|
802 } |
|
803 |
|
804 QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key, const QTransform &transform) const |
|
805 { |
|
806 QList<QFontEngineGlyphCache*> items = m_glyphIntHash.value(key); |
|
807 |
|
808 for (QList<QFontEngineGlyphCache*>::iterator it = items.begin(), end = items.end(); it != end; ++it) { |
|
809 QFontEngineGlyphCache *c = *it; |
|
810 if (qtransform_equals_no_translate(c->m_transform, transform)) { |
|
811 m_glyphCacheQueue.removeAll(c); // last used, move it up |
|
812 m_glyphCacheQueue.append(c); |
|
813 return c; |
729 return c; |
814 } |
730 } |
815 } |
731 } |
816 return 0; |
732 return 0; |
817 } |
733 } |
1368 |
1284 |
1369 int glyph_pos = 0; |
1285 int glyph_pos = 0; |
1370 for (int i = 0; i < len; ++i) { |
1286 for (int i = 0; i < len; ++i) { |
1371 bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 |
1287 bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 |
1372 && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); |
1288 && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); |
1373 if (glyphs->glyphs[glyph_pos] == 0) { |
1289 |
1374 |
1290 if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) { |
1375 QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); |
1291 QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); |
1376 for (int x = 1; x < engines.size(); ++x) { |
1292 for (int x = 1; x < engines.size(); ++x) { |
1377 QFontEngine *engine = engines.at(x); |
1293 QFontEngine *engine = engines.at(x); |
1378 if (!engine) { |
1294 if (!engine) { |
1379 const_cast<QFontEngineMulti *>(this)->loadEngine(x); |
1295 const_cast<QFontEngineMulti *>(this)->loadEngine(x); |