mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-05 14:10:27 -04:00
185 lines
No EOL
5.8 KiB
C++
185 lines
No EOL
5.8 KiB
C++
// WStringProxy.cpp: implementation of the WStringProxy class.
|
||
//
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
#include "WStringProxy.h"
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// Construction/Destruction
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
/** Funkce vytvo<76><6F> transitivn<76> uz<75>v<EFBFBD>r.
|
||
to znamen<65>, <20>e zru<72><75> v<>echny z<>et<65>zen<65> redirecty.
|
||
*/
|
||
WStringProxy *WStringProxy::TransitivniUzaver()
|
||
{
|
||
if (_operation==OpSubstr && _offset==0 && _stringSize==_baseString->GetLength())
|
||
{
|
||
WStringProxy *next=_baseString->TransitivniUzaver();
|
||
if (next==NULL) return this;
|
||
next->AddRef();
|
||
_baseString->Release();
|
||
_baseString=next;
|
||
return next;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
/** Main render procedure
|
||
It creates allocates buffer proxy and renders tree into it
|
||
Then turns self into redirect proxy a redirect self into newly created string
|
||
Rerurns pointer to newly created proxy
|
||
*/
|
||
WStringProxy *WStringProxy::RenderString()
|
||
{
|
||
if (_operation==OpMemBlck) return this;
|
||
|
||
WStringProxy *pp=TransitivniUzaver();
|
||
if (pp!=NULL) return pp->_baseString->RenderString();
|
||
|
||
WStringProxy *newProxy=WStringMemory::AllocString(NULL,_stringSize);
|
||
wchar_t *renderPtr=const_cast<wchar_t *>(newProxy->GetStringFromMemBlock());
|
||
|
||
RenderStringToBuffer(renderPtr);
|
||
|
||
newProxy->AddRef();
|
||
this->~WStringProxy();
|
||
_operation=OpSubstr;
|
||
_offset=0;
|
||
_baseString=newProxy;
|
||
|
||
return newProxy;
|
||
}
|
||
|
||
/** Function renders simple effect into buffer
|
||
Function needs buffer with nul terminated string
|
||
*/
|
||
void WStringProxy::RenderSimpleEffect(wchar_t *renderPtr)
|
||
{
|
||
assert(_operation==OpEffect);
|
||
switch (_effect)
|
||
{
|
||
case EfLower: wcslwr(renderPtr);break;
|
||
case EfUpper: wcsupr(renderPtr);break;
|
||
case EfReverse: wcsrev(renderPtr);break;
|
||
}
|
||
|
||
}
|
||
|
||
/** Light phase of rendering. Used to render string that is not
|
||
created from substring. This part is optimized for concat and user effects
|
||
When substring must be rendered, function call RenderStringToBufferSubstr to
|
||
render substring.
|
||
*/
|
||
void WStringProxy::RenderStringToBuffer(wchar_t *renderPtr)
|
||
{
|
||
WStringMemory::LockProxy(this);
|
||
switch (_operation)
|
||
{
|
||
case OpConcat:
|
||
_baseString->RenderStringToBuffer(renderPtr);
|
||
_secondString->RenderStringToBuffer(renderPtr+_baseString->GetLength());
|
||
break;
|
||
case OpSubstr:
|
||
{
|
||
_baseString->RenderStringToBufferSubstr(renderPtr,_offset,GetLength());
|
||
}
|
||
break;
|
||
case OpMemBlck:
|
||
{
|
||
const wchar_t *str=GetStringFromMemBlock();
|
||
wcsncpy(renderPtr,str,_stringSize);
|
||
}
|
||
break;
|
||
case OpEffect:
|
||
{
|
||
uint32_t offset=0;
|
||
renderPtr[_stringSize]=0; //we can append zero, because right side of string is not yet rendered
|
||
//if this is end of string, one extra character for zero is also allocated.
|
||
//efect functions can rely on it.
|
||
if (_blockData2>=256) offset=_userEffect->PreRenderString(renderPtr,_baseString->GetLength()); //call prerender to prepare begin of buffer
|
||
_baseString->RenderStringToBuffer(renderPtr+offset); //render string to rest of buffer
|
||
if (_blockData2>=256) _userEffect->RenderString(renderPtr,_baseString->GetLength()); //apply effect to buffer
|
||
else RenderSimpleEffect(renderPtr);
|
||
}
|
||
break;
|
||
};
|
||
WStringMemory::UnlockProxy(this);
|
||
}
|
||
|
||
/**
|
||
Deep phase of rendering. Function can render substrings, or render substring of two
|
||
concated strings. Function can also perform partial effect on string. Function cannot
|
||
handle partial user effect, so this effects are converted to things strings.
|
||
*/
|
||
void WStringProxy::RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size)
|
||
{
|
||
WStringMemory::LockProxy(this);
|
||
switch (_operation)
|
||
{
|
||
case OpConcat:
|
||
{
|
||
//process substring of concat
|
||
//count characters in buffer
|
||
size_t rendered;
|
||
//when string starts in left string
|
||
if (_baseString->GetLength()>offset)
|
||
{
|
||
//calculate total characters that may be rendered
|
||
rendered=_baseString->GetLength()-offset;
|
||
//but limit it to request size
|
||
if (rendered>size) rendered=size;
|
||
//render substring into buffer
|
||
_baseString->RenderStringToBufferSubstr(renderPtr,offset,rendered);
|
||
}
|
||
else
|
||
//no character has been rendered
|
||
rendered=0;
|
||
|
||
//there is still characters remained to render. We will take it from second string
|
||
if (size-rendered>0)
|
||
{
|
||
if (offset>_baseString->GetLength()) offset-=_baseString->GetLength();
|
||
else offset=0;
|
||
_secondString->RenderStringToBufferSubstr(renderPtr+rendered,offset,size-rendered);
|
||
}
|
||
}
|
||
break;
|
||
case OpSubstr:
|
||
{ //rendering substrings is very easy
|
||
offset+=_offset; //add offset of substring
|
||
assert(offset+size<=GetLength()); //check length
|
||
//render substring
|
||
this->RenderStringToBufferSubstr(renderPtr,offset,size);
|
||
}
|
||
break;
|
||
case OpMemBlck:
|
||
{
|
||
//rendering from memory, final stop in recursion
|
||
//Get pointer string
|
||
const wchar_t *str=GetStringFromMemBlock();
|
||
//copy substring from string into render buffer
|
||
wcsncpy(renderPtr,str+offset,size);
|
||
}
|
||
break;
|
||
case OpEffect:
|
||
if (_blockData2>=256) //interface cannot handle partial rendering
|
||
{
|
||
RenderString(); //convert proxy to simple redirect and render it
|
||
RenderStringToBufferSubstr(renderPtr,offset,size); //now we are able to cut out part
|
||
}
|
||
else
|
||
{
|
||
//all standard effects maps string 1:1
|
||
//first get content of substring into buffer
|
||
_baseString->RenderStringToBufferSubstr(renderPtr,offset,size);
|
||
//we can append zero, because right side of string is not yet rendered
|
||
renderPtr[size]=0;
|
||
//process effect on target
|
||
RenderSimpleEffect(renderPtr);
|
||
}
|
||
break;
|
||
};
|
||
WStringMemory::UnlockProxy(this);
|
||
} |