⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guimltextctrl.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 5 页
字号:
      // go to the next line...
      emitNewLine(textStart);
   }
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::emitTextToken(U32 textStart, U32 len)
{
   if(mCurRMargin <= mCurLMargin)
      return;

   GFont *font = mCurStyle->font->fontRes;
   Atom *a = (Atom *) mViewChunker.alloc(sizeof(Atom));
   a->url = mCurURL;

   a->style = mCurStyle;
   mCurStyle->used = true;

   a->baseLine = font->getBaseline();
   a->descent = font->getDescent();
   a->textStart = textStart;
   a->len = len;
   a->isClipped = false;
   a->next = NULL;
   *mEmitAtomPtr = a;
   mEmitAtomPtr = &(a->next);
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::processEmitAtoms()
{
   Atom *atomList = mEmitAtoms;
   mEmitAtoms = NULL;
   mEmitAtomPtr = &mEmitAtoms;

   while(atomList)
   {
      // split the tokenlist by space
      // first find the first space that the text can go into:
      BitmapRef *br = mBlockList;
      bool bailout = false;
      Atom *list = atomList;

      while(br && atomList)
      {
         // if the blocker is before the current x, ignore it.
         if(br->point.x + br->extent.x <= mCurX)
         {
            br = br->nextBlocker;
            continue;
         }
         // if cur x is in the middle of the blocker
         // advance cur x to right edge of blocker.
         if(mCurX >= br->point.x)
         {
            mCurX = br->point.x + br->extent.x;
            br = br->nextBlocker;
            continue;
         }
         // get the remaining width
         U32 right = br->point.x;
         if(right > mCurRMargin)
            right = mCurRMargin;

         //if we're clipping text, readjust
         if (mCurClipX > 0 && right > mCurClipX)
            right = mCurClipX;

         // if there's no room, break to the next line...
         if(right <= mCurX)
            break;
         // we've got some space:
         U32 width = right - mCurX;
         atomList = splitAtomListEmit(atomList, width);
         if(atomList) // there's more, so advance cur x
         {
            mCurX = br->point.x + br->extent.x;
            br = br->nextBlocker;
         }
      }
      if(mBlockList == &mSentinel && atomList == list)
      {
         if(bailout)
            return;
         else
            bailout = true;
      }
      // is there more to process for the next line?
      if(atomList)
         emitNewLine(mScanPos);
   }
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::Atom *GuiMLTextCtrl::splitAtomListEmit(Atom *list, U32 width)
{
	//取消emitted功能,则造成死循环
#define TGE_RPG_MLTEXT

   U32 totalWidth = 0;
   Atom *emitList = 0;
   Atom **emitPtr = &emitList;

   bool adjustClipAtom = false;
   Atom *clipAtom = NULL;
//#ifdef TGE_RPG_MLTEXT
   bool emitted = false;
//#endif

   while(list)
   {
      GFont *font = list->style->font->fontRes;
      U32 breakPos;

		/// Chinese 
      //FrameTemp<UTF8> tmp( (list->len) * 3 + 1 );
      //StringBuffer tmpBuff = mTextBuffer.substring(list->textStart, list->len);
      //tmpBuff.get(tmp, (list->len) * 3 + 1 );
		UTF16* tmp = mTextBuffer.getBuffer(list->textStart);

      //if we're clipping the text, we don't break within an atom, we adjust the atom to only render
      //the portion of text that does fit, and to ignore the rest...
      if (mCurClipX > 0)
      {
         //find out how many character's fit within the given width
			/// Chinese
         breakPos = font->getBreakPos(tmp, list->len, width - totalWidth, false);

         //if there isn't room for even the first character...
         if (breakPos == 0)
         {
            //set the atom's len and width to prevent it from being drawn
            list->len = 0;
            list->width = 0;
            adjustClipAtom = true;
         }

         //if our text doesn't fit within the clip region, add a "..."
         else if (breakPos != list->len)
         {
            U32 etcWidth = font->getStrNWidthPrecise("...", 3);
            breakPos = font->getBreakPos(tmp, list->len, width - totalWidth - etcWidth, false);

            //again, if there isn't even room for a single character before the "...."
            if (breakPos == 0)
            {
               //set the atom's len and width to prevent it from being drawn
               list->len = 0;
               list->width = 0;
               adjustClipAtom = true;
            }
            else
            {
               //set the char len to the break pos, and the rest of the characters in this atom will be ignored
               list->len = breakPos;
               list->width = width - totalWidth;

               //mark this one as clipped
               list->isClipped = true;
               clipAtom = NULL;
            }
         }
      
         //otherwise no need to treat this atom any differently..
         else
         {
            //set the atom width == to the string length
            list->width = font->getStrNWidthPrecise(tmp, breakPos);

            //set the pointer to the last atom that fit within the clip region
            clipAtom = list;
         }
      }
      else
      {
         breakPos = font->getBreakPos(tmp, list->len, width - totalWidth, false);
#ifdef TGE_RPG_MLTEXT
         if(breakPos == 0 
				|| (breakPos < list->len && emitted))
#else
         if(breakPos == 0 || (breakPos < list->len && mTextBuffer.getChar(list->textStart + breakPos - 1)!= ' ' && emitted))
#endif
            break;
         //set the atom width == to the string length
         list->width = font->getStrNWidthPrecise(tmp, breakPos);
      }

      //update the total width
      totalWidth += list->width;
      
      // see if this is the last atom that will fit:
      Atom *emit = list;
      
      *emitPtr = emit;
      emitPtr = &(emit->next);

#ifdef TGE_RPG_MLTEXT
		if(totalWidth >= width)
			emitted = true;
#else
      emitted = true;
#endif

      //if we're clipping, don't split the atom, otherwise, see if it needs to be split
      if(!list->isClipped && breakPos != list->len)
      {
         Atom *a = (Atom *) mViewChunker.alloc(sizeof(Atom));
         a->url = list->url;
         a->textStart = list->textStart + breakPos;
         a->len = list->len - breakPos;
         a->next = list->next;
         a->baseLine = list->baseLine;
         a->descent = list->descent;
         a->style = list->style;
         a->isClipped = false;
         
         list = a;
         emit->len = breakPos;
         break;
      }
      list = list->next;
      if(totalWidth > width)
         break;
   }

   //if we had to completely clip an atom(s), the last (partially) visible atom should be modified to include a "..."
   if (adjustClipAtom && clipAtom)
   {
      GFont *font = clipAtom->style->font->fontRes;
      U32 breakPos;

      U32 etcWidth = font->getStrNWidthPrecise("...", 3);

		/// Chinese
      //FrameTemp<UTF8> tmp( (clipAtom->len) * 3 + 1 );
      //StringBuffer tmpBuff = mTextBuffer.substring(clipAtom->textStart, clipAtom->len);
      //tmpBuff.get(tmp, (clipAtom->len) * 3 + 1 );
		UTF16* tmp = mTextBuffer.getBuffer(clipAtom->textStart);

      breakPos = font->getBreakPos(tmp, clipAtom->len, clipAtom->width - etcWidth, false);
      if (breakPos != 0)
      {
         clipAtom->isClipped = true;
         clipAtom->len = breakPos;
      }
   }

   // terminate the emit list:
   *emitPtr = 0;
   // now emit it:
   // going from mCurX to mCurX + width:
   if(mCurJustify == CenterJustify)
   {
      if ( width > totalWidth )
         mCurX += (width - totalWidth) >> 1;
   }
   else if(mCurJustify == RightJustify)
   {
      if ( width > totalWidth )
         mCurX += width - totalWidth;
   }
   while(emitList)
   {
      emitList->xStart = mCurX;
      mCurX += emitList->width;
      Atom *temp = emitList->next;
      *mLineAtomPtr = emitList;
      emitList->next = 0;
      mLineAtomPtr = &(emitList->next);
      emitList = temp;
   }
   return list;
}

//--------------------------------------------------------------------------
#ifdef TGE_CHINESE
//需要考虑GB码为双字节
static bool scanforchar(char *str, U32 &idx, char c,U32* pGBNum=NULL)
{
   U32 startidx	= idx;
	U32 nGBNum		= 0;

   while(str[idx] != c && str[idx] && str[idx] != ':' && str[idx] != '>' && str[idx] != '\n')
	{
		if(IsGB(str[idx]))
		{
			nGBNum++;
			idx+=2;
		}
		else
			idx++;
	}
	if(pGBNum)
		*pGBNum += nGBNum;
   return str[idx] == c && startidx != idx;
}
#else
static bool scanforchar(char *str, U32 &idx, char c)
{
   U32 startidx = idx;
   while(str[idx] != c && str[idx] && str[idx] != ':' && str[idx] != '>' && str[idx] != '\n')
      idx++;
   return str[idx] == c && startidx != idx;
}
#endif

//--------------------------------------------------------------------------
static S32 getHexVal(char c)
{
   if(c >= '0' && c <= '9')
      return c - '0';
   else if(c >= 'A' && c <= 'Z')
      return c - 'A' + 10;
   else if(c >= 'a' && c <= 'z')
      return c - 'a' + 10;
   return -1;
}

//--------------------------------------------------------------------------
GuiMLTextCtrl::Style *GuiMLTextCtrl::allocStyle(GuiMLTextCtrl::Style *style)
{
   Style *ret = (Style *) mViewChunker.alloc(sizeof(Style));
   ret->used = false;
   if(style)
   {
      ret->font = style->font;
      ret->color = style->color;
      ret->linkColor = style->linkColor;
      ret->linkColorHL = style->linkColorHL;
      ret->shadowColor = style->shadowColor;
      ret->shadowOffset = style->shadowOffset;
      ret->next = style->next;
   }
   else
   {
      ret->font = 0;
      ret->next = 0;
   }
   return ret;
}

//--------------------------------------------------------------------------
void GuiMLTextCtrl::reflow()
{
   AssertFatal(mAwake, "Can't reflow a sleeping control.");
   freeLineBuffers();
   mDirty = false;
   mScanPos = 0;

   mLineList = NULL;
   mLineInsert = &mLineList;

   mCurStyle = allocStyle(NULL);
   mCurStyle->font = allocFont((char *) mProfile->mFontType, dStrlen(mProfile->mFontType), mProfile->mFontSize);
   if(!mCurStyle->font)
      return;
   mCurStyle->color = mProfile->mFontColor;
   mCurStyle->shadowColor = mProfile->mFontColor;
   mCurStyle->shadowOffset.set(0,0);
   mCurStyle->linkColor = mProfile->mFontColors[GuiControlProfile::ColorUser0];
   mCurStyle->linkColorHL = mProfile->mFontColors[GuiControlProfile::ColorUser1];

   U32 width = mBounds.extent.x;

   mCurLMargin = 0;
   mCurRMargin = width;
   mCurJustify = LeftJustify;
   mCurDiv = 0;
   mCurY = 0;
   mCurX = 0;
   mCurClipX = 0;
   mLineAtoms = NULL;
   mLineAtomPtr = &mLineAtoms;

   mSentinel.point.x = width;
   mSentinel.point.y = 0;
   mSentinel.extent.x = 0;
   mSentinel.extent.y = 0x7FFFFF;
   mSentinel.nextBlocker = NULL;
   mLineStart = 0;
   mEmitAtoms = 0;
   mMaxY = 0;
   mEmitAtomPtr = &mEmitAtoms;

   mBlockList = &mSentinel;

   Font *nextFont;
   LineTag *nextTag;
   mTabStops = 0;
   mCurTabStop = 0;
   mTabStopCount = 0;
   mCurURL = 0;
   Style *newStyle;

   U32 textStart;
   U32 len;
   U32 idx;
   U32 sizidx;

   for(;;)
   {
      UTF16 curChar = mTextBuffer.getChar(mScanPos);

      if(!curChar)
         break;

      if(curChar == '\n')
      {
         textStart = mScanPos;
         len = 1;
         mScanPos++;
         processEmitAtoms();
         emitNewLine(textStart);
         mCurDiv = 0;
         continue;
      }

      if(curChar == '\t')
      {
         textStart = mScanPos;
         len = 1;
         mScanPos++;
         processEmitAtoms();
#ifdef TGE_RPG
			U32 nWidth;
			if(m_nFontDefaultHeight== 0)
			{	
				if(mTabStopCount)
				{
					if(mCurTabStop < mTabStopCount)
					{
						nWidth = mTabStops[mCurTabStop];
						if(mCurX - mCurLMargin < nWidth)
							mCurX = mCurLMargin + nWidth;
						mCurTabStop++;
					}
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -