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"
32 #include <tools/svwin.h>
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()
61 void GrSegRecord::reuse(rtl::OUString
* rope
, TextSourceAdaptor
* textSrc
, gr::Segment
* seg
, bool bIsRtl
)
69 m_pStr
= textSrc
->getLayoutArgs().mpStr
+ seg
->startCharacter();
70 m_startChar
= seg
->startCharacter();
74 void GrSegRecord::clearVectors()
78 mvChar2BaseGlyph
.clear();
82 void GrSegRecord::clear()
86 OutputDebugString("GrSegRecord locked!");
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
);
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
;
140 record
->reuse(pRope
, adapter
, seg
, bIsRtl
);
142 record
= new GrSegRecord(pRope
, adapter
, seg
, bIsRtl
);
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
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
);
172 GraphiteRopeMap::value_type
mapEntry(record
->m_rope
->hashCode(), record
);
173 m_ropeMap
.insert(mapEntry
);
174 // remove the old record
176 record
->m_lockCount
++;
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
++;