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