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 10cdf0e10cSrcweir * 11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 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 54cdf0e10cSrcweir GrSegRecord::~GrSegRecord() 55cdf0e10cSrcweir { 56cdf0e10cSrcweir clear(); 57cdf0e10cSrcweir } 58cdf0e10cSrcweir 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 72cdf0e10cSrcweir void GrSegRecord::clearVectors() 73cdf0e10cSrcweir { 74cdf0e10cSrcweir mvGlyphs.clear(); 75cdf0e10cSrcweir mvCharDxs.clear(); 76cdf0e10cSrcweir mvChar2BaseGlyph.clear(); 77cdf0e10cSrcweir mvGlyph2Char.clear(); 78cdf0e10cSrcweir } 79cdf0e10cSrcweir 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 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