merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / glyphs / graphite_cache.cxx
blob8c514c611d2c94a3fe6dc59efb6b14c8c6d1c345
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #ifdef WNT
32 #include <tools/svwin.h>
33 #include <svsys.h>
34 #endif
36 #include <tools/debug.hxx>
37 #include <vcl/sallayout.hxx>
39 #include <graphite/GrClient.h>
40 #include <graphite/Segment.h>
42 #include <rtl/ustring.hxx>
43 #include <vcl/graphite_layout.hxx>
44 #include <vcl/graphite_cache.hxx>
46 #include "graphite_textsrc.hxx"
48 GrSegRecord::GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
49 : m_rope(rope), m_text(textSrc), m_seg(seg), m_nextKey(NULL),
50 m_fontScale(0.0f), mbIsRtl(bIsRtl), m_lockCount(0)
52 m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
53 m_startChar = seg->startCharacter();
56 GrSegRecord::~GrSegRecord()
58 clear();
61 void GrSegRecord::reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
63 clear();
64 mnWidth = 0;
65 m_rope = rope;
66 m_text = textSrc;
67 m_seg = seg;
68 m_nextKey = NULL;
69 m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
70 m_startChar = seg->startCharacter();
71 mbIsRtl = bIsRtl;
74 void GrSegRecord::clearVectors()
76 mvGlyphs.clear();
77 mvCharDxs.clear();
78 mvChar2BaseGlyph.clear();
79 mvGlyph2Char.clear();
82 void GrSegRecord::clear()
84 #ifdef GR_DEBUG_TEXT
85 if (m_lockCount != 0)
86 OutputDebugString("GrSegRecord locked!");
87 #endif
88 clearVectors();
89 delete m_rope;
90 delete m_seg;
91 delete m_text;
92 m_rope = NULL;
93 m_seg = NULL;
94 m_text = NULL;
95 m_fontScale = 0.0f;
96 m_lockCount = 0;
99 GrSegRecord * GraphiteSegmentCache::cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl)
101 GrSegRecord * record = NULL;
102 // We keep a record of the oldest key and the last key added
103 // when the next key is added, the record for the prevKey's m_nextKey field
104 // is updated to the newest key so that m_oldestKey can be updated to the
105 // next oldest key when the record for m_oldestKey is deleted
106 if (m_segMap.size() > SEG_CACHE_SIZE)
108 GraphiteSegMap::iterator oldestPair = m_segMap.find(reinterpret_cast<long>(m_oldestKey));
109 // oldest record may no longer exist if a buffer was changed
110 if (oldestPair != m_segMap.end())
112 record = oldestPair->second;
113 m_segMap.erase(reinterpret_cast<long>(m_oldestKey));
114 GrRMEntry range = m_ropeMap.equal_range((*(record->m_rope)).hashCode());
115 while (range.first != range.second)
117 if (range.first->second == record)
119 m_ropeMap.erase(range.first);
120 break;
122 ++range.first;
124 m_oldestKey = record->m_nextKey;
125 // record will be reused, so don't delete
130 // const int seg_char_limit = min(adapter->maLayoutArgs().mnLength,
131 // adapter->maLayoutArgs().mnEndCharPos
132 // + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
133 // if (seg->stopCharacter() - seg->startCharacter() <= 0)
134 // OutputDebugString("Invalid seg indices\n");
135 rtl::OUString * pRope = new rtl::OUString(adapter->getLayoutArgs().mpStr + seg->startCharacter(),
136 seg->stopCharacter() - seg->startCharacter());
137 if (!pRope) return NULL;
138 bool reuse = false;
139 if (record)
140 record->reuse(pRope, adapter, seg, bIsRtl);
141 else
142 record = new GrSegRecord(pRope, adapter, seg, bIsRtl);
143 if (!record)
145 delete pRope;
146 return NULL;
148 GraphiteSegMap::iterator iMap =
149 m_segMap.find(reinterpret_cast<long>(record->m_pStr));
150 if (iMap != m_segMap.end())
152 // the buffer has changed, so the old cached Segment is useless
153 reuse = true;
154 GrSegRecord * found = iMap->second;
155 // Note: we reuse the old next key to avoid breaking our history
156 // chain. This means it will be prematurely deleted, but this is
157 // unlikely to happen very often.
158 record->m_nextKey = found->m_nextKey;
159 // overwrite the old record
160 m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
161 // erase the old rope key and save the new one
162 GrRMEntry range = m_ropeMap.equal_range((*(found->m_rope)).hashCode());
163 while (range.first != range.second)
165 if (range.first->second == found)
167 m_ropeMap.erase(range.first);
168 break;
170 ++range.first;
172 GraphiteRopeMap::value_type mapEntry(record->m_rope->hashCode(), record);
173 m_ropeMap.insert(mapEntry);
174 // remove the old record
175 delete found;
176 record->m_lockCount++;
177 return record;
179 m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
180 GraphiteRopeMap::value_type mapEntry((*(record->m_rope)).hashCode(), record);
181 m_ropeMap.insert(mapEntry);
183 if (m_oldestKey == NULL)
185 m_oldestKey = record->m_pStr;
186 m_prevKey = record->m_pStr;
188 else if (reuse == false)
190 DBG_ASSERT(m_segMap.count(reinterpret_cast<long>(m_prevKey)),
191 "Previous key got lost somehow!");
192 m_segMap.find(reinterpret_cast<long>(m_prevKey))
193 ->second->m_nextKey = record->m_pStr;
194 m_prevKey = record->m_pStr;
196 record->m_lockCount++;
197 return record;