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