1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*9f62ea84SAndrew Rist * distributed with this work for additional information
6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
10*9f62ea84SAndrew Rist *
11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*9f62ea84SAndrew Rist *
13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
17*9f62ea84SAndrew Rist * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist * under the License.
19*9f62ea84SAndrew Rist *
20*9f62ea84SAndrew Rist *************************************************************/
21*9f62ea84SAndrew Rist
22*9f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #ifdef WNT
28cdf0e10cSrcweir #include <tools/svwin.h>
29cdf0e10cSrcweir #include <svsys.h>
30cdf0e10cSrcweir #endif
31cdf0e10cSrcweir
32cdf0e10cSrcweir #include <tools/debug.hxx>
33cdf0e10cSrcweir #include <sallayout.hxx>
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include <preextstl.h>
36cdf0e10cSrcweir #include <graphite/GrClient.h>
37cdf0e10cSrcweir #include <graphite/Segment.h>
38cdf0e10cSrcweir #include <postextstl.h>
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include <rtl/ustring.hxx>
41cdf0e10cSrcweir #include <graphite_layout.hxx>
42cdf0e10cSrcweir #include <graphite_cache.hxx>
43cdf0e10cSrcweir
44cdf0e10cSrcweir #include "graphite_textsrc.hxx"
45cdf0e10cSrcweir
GrSegRecord(rtl::OUString * rope,TextSourceAdaptor * textSrc,gr::Segment * seg,bool bIsRtl)46cdf0e10cSrcweir GrSegRecord::GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
47cdf0e10cSrcweir : m_rope(rope), m_text(textSrc), m_seg(seg), m_nextKey(NULL),
48cdf0e10cSrcweir m_fontScale(0.0f), mbIsRtl(bIsRtl), m_lockCount(0)
49cdf0e10cSrcweir {
50cdf0e10cSrcweir m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
51cdf0e10cSrcweir m_startChar = seg->startCharacter();
52cdf0e10cSrcweir }
53cdf0e10cSrcweir
~GrSegRecord()54cdf0e10cSrcweir GrSegRecord::~GrSegRecord()
55cdf0e10cSrcweir {
56cdf0e10cSrcweir clear();
57cdf0e10cSrcweir }
58cdf0e10cSrcweir
reuse(rtl::OUString * rope,TextSourceAdaptor * textSrc,gr::Segment * seg,bool bIsRtl)59cdf0e10cSrcweir void GrSegRecord::reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
60cdf0e10cSrcweir {
61cdf0e10cSrcweir clear();
62cdf0e10cSrcweir mnWidth = 0;
63cdf0e10cSrcweir m_rope = rope;
64cdf0e10cSrcweir m_text = textSrc;
65cdf0e10cSrcweir m_seg = seg;
66cdf0e10cSrcweir m_nextKey = NULL;
67cdf0e10cSrcweir m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
68cdf0e10cSrcweir m_startChar = seg->startCharacter();
69cdf0e10cSrcweir mbIsRtl = bIsRtl;
70cdf0e10cSrcweir }
71cdf0e10cSrcweir
clearVectors()72cdf0e10cSrcweir void GrSegRecord::clearVectors()
73cdf0e10cSrcweir {
74cdf0e10cSrcweir mvGlyphs.clear();
75cdf0e10cSrcweir mvCharDxs.clear();
76cdf0e10cSrcweir mvChar2BaseGlyph.clear();
77cdf0e10cSrcweir mvGlyph2Char.clear();
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
clear()80cdf0e10cSrcweir void GrSegRecord::clear()
81cdf0e10cSrcweir {
82cdf0e10cSrcweir #ifdef GR_DEBUG_TEXT
83cdf0e10cSrcweir if (m_lockCount != 0)
84cdf0e10cSrcweir OutputDebugString("GrSegRecord locked!");
85cdf0e10cSrcweir #endif
86cdf0e10cSrcweir clearVectors();
87cdf0e10cSrcweir delete m_rope;
88cdf0e10cSrcweir delete m_seg;
89cdf0e10cSrcweir delete m_text;
90cdf0e10cSrcweir m_rope = NULL;
91cdf0e10cSrcweir m_seg = NULL;
92cdf0e10cSrcweir m_text = NULL;
93cdf0e10cSrcweir m_fontScale = 0.0f;
94cdf0e10cSrcweir m_lockCount = 0;
95cdf0e10cSrcweir }
96cdf0e10cSrcweir
cacheSegment(TextSourceAdaptor * adapter,gr::Segment * seg,bool bIsRtl)97cdf0e10cSrcweir GrSegRecord * GraphiteSegmentCache::cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl)
98cdf0e10cSrcweir {
99cdf0e10cSrcweir GrSegRecord * record = NULL;
100cdf0e10cSrcweir // We keep a record of the oldest key and the last key added
101cdf0e10cSrcweir // when the next key is added, the record for the prevKey's m_nextKey field
102cdf0e10cSrcweir // is updated to the newest key so that m_oldestKey can be updated to the
103cdf0e10cSrcweir // next oldest key when the record for m_oldestKey is deleted
104cdf0e10cSrcweir if (m_segMap.size() > m_nSegCacheSize)
105cdf0e10cSrcweir {
106cdf0e10cSrcweir GraphiteSegMap::iterator oldestPair = m_segMap.find(reinterpret_cast<long>(m_oldestKey));
107cdf0e10cSrcweir // oldest record may no longer exist if a buffer was changed
108cdf0e10cSrcweir if (oldestPair != m_segMap.end())
109cdf0e10cSrcweir {
110cdf0e10cSrcweir record = oldestPair->second;
111cdf0e10cSrcweir m_segMap.erase(reinterpret_cast<long>(m_oldestKey));
112cdf0e10cSrcweir GrRMEntry range = m_ropeMap.equal_range((*(record->m_rope)).hashCode());
113cdf0e10cSrcweir while (range.first != range.second)
114cdf0e10cSrcweir {
115cdf0e10cSrcweir if (range.first->second == record)
116cdf0e10cSrcweir {
117cdf0e10cSrcweir m_ropeMap.erase(range.first);
118cdf0e10cSrcweir break;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir ++range.first;
121cdf0e10cSrcweir }
122cdf0e10cSrcweir m_oldestKey = record->m_nextKey;
123cdf0e10cSrcweir // record will be reused, so don't delete
124cdf0e10cSrcweir }
125cdf0e10cSrcweir }
126cdf0e10cSrcweir
127cdf0e10cSrcweir
128cdf0e10cSrcweir // const int seg_char_limit = min(adapter->maLayoutArgs().mnLength,
129cdf0e10cSrcweir // adapter->maLayoutArgs().mnEndCharPos
130cdf0e10cSrcweir // + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
131cdf0e10cSrcweir // if (seg->stopCharacter() - seg->startCharacter() <= 0)
132cdf0e10cSrcweir // OutputDebugString("Invalid seg indices\n");
133cdf0e10cSrcweir rtl::OUString * pRope = new rtl::OUString(adapter->getLayoutArgs().mpStr + seg->startCharacter(),
134cdf0e10cSrcweir seg->stopCharacter() - seg->startCharacter());
135cdf0e10cSrcweir if (!pRope) return NULL;
136cdf0e10cSrcweir bool reuse = false;
137cdf0e10cSrcweir if (record)
138cdf0e10cSrcweir record->reuse(pRope, adapter, seg, bIsRtl);
139cdf0e10cSrcweir else
140cdf0e10cSrcweir record = new GrSegRecord(pRope, adapter, seg, bIsRtl);
141cdf0e10cSrcweir if (!record)
142cdf0e10cSrcweir {
143cdf0e10cSrcweir delete pRope;
144cdf0e10cSrcweir return NULL;
145cdf0e10cSrcweir }
146cdf0e10cSrcweir GraphiteSegMap::iterator iMap =
147cdf0e10cSrcweir m_segMap.find(reinterpret_cast<long>(record->m_pStr));
148cdf0e10cSrcweir if (iMap != m_segMap.end())
149cdf0e10cSrcweir {
150cdf0e10cSrcweir // the buffer has changed, so the old cached Segment is useless
151cdf0e10cSrcweir reuse = true;
152cdf0e10cSrcweir GrSegRecord * found = iMap->second;
153cdf0e10cSrcweir // Note: we reuse the old next key to avoid breaking our history
154cdf0e10cSrcweir // chain. This means it will be prematurely deleted, but this is
155cdf0e10cSrcweir // unlikely to happen very often.
156cdf0e10cSrcweir record->m_nextKey = found->m_nextKey;
157cdf0e10cSrcweir // overwrite the old record
158cdf0e10cSrcweir m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
159cdf0e10cSrcweir // erase the old rope key and save the new one
160cdf0e10cSrcweir GrRMEntry range = m_ropeMap.equal_range((*(found->m_rope)).hashCode());
161cdf0e10cSrcweir while (range.first != range.second)
162cdf0e10cSrcweir {
163cdf0e10cSrcweir if (range.first->second == found)
164cdf0e10cSrcweir {
165cdf0e10cSrcweir m_ropeMap.erase(range.first);
166cdf0e10cSrcweir break;
167cdf0e10cSrcweir }
168cdf0e10cSrcweir ++range.first;
169cdf0e10cSrcweir }
170cdf0e10cSrcweir GraphiteRopeMap::value_type mapEntry(record->m_rope->hashCode(), record);
171cdf0e10cSrcweir m_ropeMap.insert(mapEntry);
172cdf0e10cSrcweir // remove the old record
173cdf0e10cSrcweir delete found;
174cdf0e10cSrcweir record->m_lockCount++;
175cdf0e10cSrcweir return record;
176cdf0e10cSrcweir }
177cdf0e10cSrcweir m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
178cdf0e10cSrcweir GraphiteRopeMap::value_type mapEntry((*(record->m_rope)).hashCode(), record);
179cdf0e10cSrcweir m_ropeMap.insert(mapEntry);
180cdf0e10cSrcweir
181cdf0e10cSrcweir if (m_oldestKey == NULL)
182cdf0e10cSrcweir {
183cdf0e10cSrcweir m_oldestKey = record->m_pStr;
184cdf0e10cSrcweir m_prevKey = record->m_pStr;
185cdf0e10cSrcweir }
186cdf0e10cSrcweir else if (reuse == false)
187cdf0e10cSrcweir {
188cdf0e10cSrcweir DBG_ASSERT(m_segMap.count(reinterpret_cast<long>(m_prevKey)),
189cdf0e10cSrcweir "Previous key got lost somehow!");
190cdf0e10cSrcweir m_segMap.find(reinterpret_cast<long>(m_prevKey))
191cdf0e10cSrcweir ->second->m_nextKey = record->m_pStr;
192cdf0e10cSrcweir m_prevKey = record->m_pStr;
193cdf0e10cSrcweir }
194cdf0e10cSrcweir record->m_lockCount++;
195cdf0e10cSrcweir return record;
196cdf0e10cSrcweir }
197