void Segment::splice(size_t offset, size_t length, Slot * const startSlot, Slot * endSlot, const Slot * srcSlot, const size_t numGlyphs) { size_t numChars = length; extendLength(numGlyphs - length); // remove any extra if (numGlyphs < length) { Slot * end = endSlot->next(); do { endSlot = endSlot->prev(); freeSlot(endSlot->next()); } while (numGlyphs < --length); endSlot->next(end); if (end) end->prev(endSlot); } else { // insert extra slots if needed while (numGlyphs > length) { Slot * extra = newSlot(); if (!extra) return; extra->prev(endSlot); extra->next(endSlot->next()); endSlot->next(extra); if (extra->next()) extra->next()->prev(extra); if (m_last == endSlot) m_last = extra; endSlot = extra; ++length; } } endSlot = endSlot->next(); assert(numGlyphs == length); assert(offset + numChars <= m_numCharinfo); Slot * indexmap[eMaxSpliceSize*3]; assert(numGlyphs < sizeof indexmap/sizeof *indexmap); Slot * slot = startSlot; for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i) indexmap[i] = slot; for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next()) { slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars); if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]); if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()]; if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()]; } }
SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime) : m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL), m_attr(NULL), m_justs(NULL), m_accessCount(0), m_lastAccess(cacheTime) { if (m_unicode) for (uint16 i = 0; i < length; i++) m_unicode[i] = cmapGlyphs[i]; const size_t glyphCount = seg->slotCount(), sizeof_sjust = SlotJustify::size_of(seg->silf()->numJustLevels()); if (!glyphCount) return; size_t num_justs = 0, justs_pos = 0; if (seg->hasJustification()) { for (const Slot * s = seg->first(); s; s = s->next()) { if (s->m_justs == 0) continue; ++num_justs; } m_justs = gralloc<byte>(sizeof_sjust * num_justs); } const Slot * slot = seg->first(); m_glyph = new Slot[glyphCount]; m_attr = gralloc<int16>(glyphCount * seg->numAttrs()); if (!m_glyph || (!m_attr && seg->numAttrs())) return; m_glyphLength = glyphCount; Slot * slotCopy = m_glyph; m_glyph->prev(NULL); uint16 pos = 0; while (slot) { slotCopy->userAttrs(m_attr + pos * seg->numAttrs()); slotCopy->m_justs = m_justs ? reinterpret_cast<SlotJustify *>(m_justs + justs_pos++ * sizeof_sjust) : 0; slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs(), seg->silf()->numJustLevels(), length); slotCopy->index(pos); if (slot->firstChild()) slotCopy->m_child = m_glyph + slot->firstChild()->index(); if (slot->attachedTo()) slotCopy->attachTo(m_glyph + slot->attachedTo()->index()); if (slot->nextSibling()) slotCopy->m_sibling = m_glyph + slot->nextSibling()->index(); slot = slot->next(); ++slotCopy; ++pos; if (slot) { slotCopy->prev(slotCopy-1); (slotCopy-1)->next(slotCopy); } } }
SegCacheEntry::SegCacheEntry(const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset, long long cacheTime) : m_glyphLength(0), m_unicode(gralloc<uint16>(length)), m_glyph(NULL), m_attr(NULL), m_accessCount(0), m_lastAccess(cacheTime) { for (uint16 i = 0; i < length; i++) { m_unicode[i] = cmapGlyphs[i]; } size_t glyphCount = seg->slotCount(); const Slot * slot = seg->first(); m_glyph = new Slot[glyphCount]; m_attr = gralloc<uint16>(glyphCount * seg->numAttrs()); m_glyphLength = glyphCount; Slot * slotCopy = m_glyph; m_glyph->prev(NULL); struct Index2Slot { Index2Slot(uint16 i, const Slot * s) : m_i(i), m_slot(s) {}; Index2Slot() : m_i(0), m_slot(NULL) {}; uint16 m_i; const Slot * m_slot; }; struct Index2Slot parentGlyphs[eMaxSpliceSize]; struct Index2Slot childGlyphs[eMaxSpliceSize]; uint16 numParents = 0; uint16 numChildren = 0; uint16 pos = 0; while (slot) { slotCopy->userAttrs(m_attr + pos * seg->numAttrs()); slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs()); if (slot->firstChild()) { new(parentGlyphs + numParents) Index2Slot( pos, slot ); ++numParents; } if (slot->attachedTo()) { new(childGlyphs + numChildren) Index2Slot( pos, slot ); ++numChildren; } slot = slot->next(); ++slotCopy; ++pos; if (slot) { slotCopy->prev(slotCopy-1); (slotCopy-1)->next(slotCopy); } } // loop over the attached children finding their siblings and parents for (int16 i = 0; i < numChildren; i++) { if (childGlyphs[i].m_slot->nextSibling()) { for (int16 j = i; j < numChildren; j++) { if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i); break; } } if (!m_glyph[childGlyphs[i].m_i].nextSibling()) { // search backwards for (int16 j = i-1; j >= 0; j--) { if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i); break; } } } } // now find the parent glyph for (int16 j = 0; j < numParents; j++) { if (childGlyphs[i].m_slot->attachedTo() == parentGlyphs[j].m_slot) { m_glyph[childGlyphs[i].m_i].attachTo(m_glyph + parentGlyphs[j].m_i); if (parentGlyphs[j].m_slot->firstChild() == childGlyphs[i].m_slot) { m_glyph[parentGlyphs[j].m_i].child(m_glyph + childGlyphs[i].m_i); } } } } }
void CHM_Static::Update () { Fvector& view = Device.vCameraPosition; int v_x = iFloor(view.x/dhm_size); int v_z = iFloor(view.z/dhm_size); // ***** SCROLL if (v_x!=c_x) { if (v_x>c_x) { // scroll matrix to left ++c_x; for (int z=0; z<dhm_matrix; ++z) { Slot* S = data[z][0]; if (S->bReady) { S->bReady = FALSE; task.push_back(S); } for (int x=1; x<dhm_matrix; ++x) data[z][x-1] = data[z][x]; data[z][dhm_matrix-1] = S; S->set (c_x-dhm_line+dhm_matrix-1, c_z-dhm_line+z); } } else { // scroll matrix to right --c_x; for (int z=0; z<dhm_matrix; ++z) { Slot* S = data[z][dhm_matrix-1]; if (S->bReady) { S->bReady = FALSE; task.push_back(S); } for (int x=dhm_matrix-1; x>0; --x) data[z][x] = data[z][x-1]; data[z][0] = S; S->set (c_x-dhm_line+0,c_z-dhm_line+z); } } } if (v_z!=c_z) { if (v_z>c_z) { // scroll matrix down a bit ++c_z; for (int x=0; x<dhm_matrix; ++x) { Slot* S = data[dhm_matrix-1][x]; if (S->bReady) { S->bReady = FALSE; task.push_back(S); } for (int z=dhm_matrix-1; z>0; --z) data[z][x] = data[z-1][x]; data[0][x] = S; S->set (c_x-dhm_line+x,c_z-dhm_line+0); } } else { // scroll matrix up --c_z; for (int x=0; x<dhm_matrix; ++x) { Slot* S = data[0][x]; if (S->bReady) { S->bReady = FALSE; task.push_back(S); } for (int z=0; z<dhm_matrix; ++z) data[z-1][x] = data[z][x]; data[dhm_matrix-1][x] = S; S->set (c_x-dhm_line+x,c_z-dhm_line+dhm_matrix-1); } } } // ***** perform TASKs for (int taskid=0; (taskid<tasksPerFrame) && (!task.empty()); ++taskid) { Slot* S = task.back (); task.pop_back(); S->bReady = TRUE; // Build BBox Fbox bb; bb.min.set (S->x*dhm_size, view.y-limit_down, S->z*dhm_size); bb.max.set (bb.min.x+dhm_size, view.y+limit_up, bb.min.z+dhm_size); bb.grow (EPS_L); // Select polygons XRC.BBoxMode (0); // BBOX_TRITEST XRC.BBoxCollide (precalc_identity,g_pGameLevel->ObjectSpace.GetStaticModel(),precalc_identity,bb); u32 triCount = XRC.GetBBoxContactCount(); if (0==triCount) { S->clear (); continue; } // Cull polys RAPID::tri* tris = g_pGameLevel->ObjectSpace.GetStaticTris(); Fvector vecUP; vecUP.set(0,1,0); for (u32 tid=0; tid<triCount; ++tid) { RAPID::tri& T = tris[XRC.BBoxContact[tid].id]; Poly P; Fvector N; P.v[0].set (*T.verts[0]); P.v[1].set (*T.verts[1]); P.v[2].set (*T.verts[2]); N.mknormal (P.v[0],P.v[1],P.v[2]); if (N.dotproduct(vecUP)<=0) continue; polys.push_back (P); } // Perform testing for (int z=0; z<dhm_precision; ++z) { for (int x=0; x<dhm_precision; ++x) { float rx = (float(x)/float(dhm_precision))*dhm_size + bb.min.x; float rz = (float(z)/float(dhm_precision))*dhm_size + bb.min.z; float ry = bb.min.y-5; Fvector pos; pos.set(rx,bb.max.y,rz); Fvector dir; dir.set(0,-1,0); float r_u,r_v,r_range; for (u32 tid=0; tid<polys.size(); ++tid) { if (RAPID::TestRayTri(pos,dir,polys[tid].v,r_u,r_v,r_range,TRUE)) { if (r_range>=0) { float y_test = pos.y - r_range; if (y_test>ry) ry = y_test; } } } S->data[z][x] = ry; } } } }