示例#1
0
int
reflow(struct textLine *ln, int tillend)
{
	int len, i;
	struct textLine *nextln;
	while (ln && ln->next && !ln->br) {
		nextln = ln->next;
		if ((ln->selected && !nextln->selected)
		    || (!ln->selected && nextln->selected)) {
			ln = nextln;
			continue;
		}
		if (!ln->len) {
			nextln->prev = ln->prev;
			if (nextln->next)
				nextln->next->prev = ln;
			keepSelect(ln);
			*ln = *nextln;	//curline 可能正指向 ln, 所以释放 nextln 而不是 ln
			free(nextln);
			ln->changed = 1;
			continue;
		}
		len = min(MAXLINELEN - ln->len, nextln->len);
		if (len) {
			memcpy(ln->text + ln->len, nextln->text, len);
			//从下一行抓取的字符数
			len =
			    measureLine(ln->text, ln->len + len, MAXLINELEN, 0,
					&i) - ln->len;
		}
		if (nextln->len && len <= 0)
			break;
		ln->len += len;
		nextln->len -= len;
		memmove(nextln->text, nextln->text + len, nextln->len);
		ln->changed = 1;
		nextln->changed = 1;
		if (!nextln->len
		    && measureWidth(ln->text, ln->len) < MAXLINELEN) {
			ln->next = nextln->next;
			if (nextln->next)
				nextln->next->prev = ln;
			if (nextln->br)
				ln->br = 1;
			keepSelect(nextln);
			free(nextln);
			if (ln->br)
				break;
			nextln = ln->next;
		}
		ln = nextln;
	}
	return 0;
}
示例#2
0
static void
insertChar(struct edit *edit, const char ch)
{
	struct textLine *ln = edit->curline, *newln;
	int len, width;
	if (!edit->overwrite)
		memmove(ln->text + edit->col + 1, ln->text + edit->col,
			ln->len - edit->col);
	ln->text[edit->col] = ch;
	edit->col++;
	edit->colcur = measureWidth(ln->text, edit->col);
	if (!edit->overwrite || edit->col > ln->len)
		ln->len++;
	ln->changed = 1;
	len = measureLine(ln->text, ln->len, MAXLINELEN, 0, &width);
	if (len == ln->len && width < MAXLINELEN) {
		edit->position = edit->colcur;
		return;
	}
	newln = allocNextLine(ln);
	newln->br = ln->br;
	ln->br = 0;
	memcpy(newln->text, ln->text + len, ln->len - len);
	newln->len = ln->len - len;
	ln->len = len;
	edit->redrawall = 1;
	reflow(newln, 0);
	if (edit->col > len || edit->colcur >= MAXLINELEN) {
		edit->curline = ln->next;
		edit->col = edit->col - len;
		edit->colcur = measureWidth(edit->curline->text, edit->col);
		edit->line++;
		edit->linecur++;
	}
	edit->position = edit->colcur;
}
示例#3
0
void Font::renderString(
    const std::wstring & str,
    glm::vec2 & cursor,
    float fontSize,
    float maxWidth) {
  float scale = Text::Font::DTP_TO_METERS * fontSize / mFontSize;
  bool wrap = (maxWidth == maxWidth);
  if (wrap) {
    maxWidth /= scale;
  }

  gl::MatrixStack & mv = gl::Stacks::modelview();
  size_t mvDepth = mv.size();

  glm::vec4 aspectTest = gl::Stacks::projection().top() * glm::vec4(1, 1, 0, 1);
  float aspect = std::abs(aspectTest.x / aspectTest.y);
  mv.push().translate(cursor).translate(glm::vec2(0, scale * -mAscent));

  // scale the modelview from into font units
  mv.scale(scale);
  gl::ProgramPtr program = GlUtils::getProgram(
      Resource::SHADERS_TEXT_VS,
      Resource::SHADERS_TEXT_FS);

  program->use();
  program->setUniform("Color", glm::vec4(1));
  program->setUniform("Font", 0);
  program->setUniform4x4f("Projection",
      gl::Stacks::projection().top());

  mTexture->bind();
  mGeometry->bindVertexArray();

  std::vector<std::wstring> tokens = Tokenize(str);

  // Stores how far we've moved from the start of the string, in DTP units
  glm::vec2 advance;
  static std::wstring SPACE = toUtf16(" ");
  for_each(tokens.begin(), tokens.end(), [&](const std::wstring & token) {
    float tokenWidth = measureWidth(token, fontSize) ;
    if (wrap && 0 != advance.x && (advance.x + tokenWidth) > maxWidth) {
      advance.x = 0;
      advance.y -= (mAscent + mDescent);
    }

    for_each(token.begin(), token.end(), [&](::uint16_t id) {
      if ('\n' == id) {
        advance.x = 0;
        advance.y -= (mAscent + mDescent);
        return;
      }

      if (!contains(id)) {
        id = '?';
      }

      // get metrics for this character to speed up measurements
      const Font::Metrics & m = getMetrics(id);

      if (wrap && ((advance.x + m.d) > maxWidth)) {
        advance.x = 0;
        advance.y -= (mAscent + mDescent);
      }

      // We create an offset vec2 to hold the local offset of this character
      // This includes compensating for the inverted Y axis of the font
      // coordinates
      glm::vec2 offset(advance);
      offset.y -= m.size.y;
      // Bind the new position
      mv.push().translate(offset).apply(program).pop();
      // Render the item
      glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void*)(m.indexOffset * sizeof(GLuint)));
      advance.x += m.d;//+ m.offset.x;// font->getAdvance(m, mFontSize);
    });
    advance.x += getMetrics(' ').d;
  });

  gl::VertexArray::unbind();
  gl::Texture2d::unbind();
  gl::Program::clear();
  mv.pop();
  //cursor.x += advance * scale;
}
示例#4
0
float Font::measureWidth(const std::wstring &text,
    float fontSize,
    bool precise) const {
  return measureWidth(text, 0, text.length(), fontSize, precise);
}
示例#5
0
void wyBitmapFontLabel::updateContentSize() {
	// remove all quads in all atlas
	wyArrayEach(m_atlasList, clearAtlas, NULL);

	// if null, do nothing
	if(!m_text)
		return;

	// break line into a vector
	vector<const char*>* lines = wyUtils::breakLines(m_text, m_font, m_lineWidth, m_spaceWidth, m_tabSize);

	// get width first because we need support text alignment
	vector<float>* widthList = measureWidth(lines);
	
	// get max width
	float maxWidth = 0;
	for(vector<float>::iterator iter = widthList->begin(); iter != widthList->end(); iter++) {
		maxWidth = MAX(maxWidth, *iter);
	}
	
	// line number
	int line = 0;
	
	// real width of final render
	float width = 0;

	// final render y position
	float y = 0;

	// prev line height
	float prevLineHeight = 0;

	// render line one by one
	for(vector<const char*>::iterator iter = lines->begin(); iter != lines->end(); iter++, line++) {
		char* p = (char*)(*iter);
		float x = 0;
		float lineOffset = 0;
		float charWidth, charHeight;
		bool firstLineChar = true;
		float currentLineHeight = 0;

		// line offset
		switch(m_alignment) {
			case LEFT:
				lineOffset = 0;
				break;
			case CENTER:
				lineOffset = (maxWidth - widthList->at(line)) / 2;
				break;
			case RIGHT:
				lineOffset = maxWidth - widthList->at(line);
				break;
		}

		// if first char of this line, add line spacing
		if(line > 0) {
			y += m_lineSpacing;
			if(prevLineHeight == 0)
				y += m_font->getEmptyLineHeight();
			else
				y += prevLineHeight;
		}

	    while(*p != 0) {
	    	// get char integer
	    	int c = 0;
	    	int b = wyUtils::getUTF8Bytes(*p);
	    	while(b-- > 0) {
	    		c <<= 8;
	    		c |= *p & 0xff;
	    		p++;
	    	}

	        wyCharInfo* pCi = m_font->getCharInfo(c);
	        if(pCi) {
	        	// get char size
	        	charWidth = pCi->texRect.width;
	        	charHeight = pCi->texRect.height;

				// if not first char of line, add left padding
				if(!firstLineChar) {
					x += pCi->left;
				}

				// choose max height as line height
				currentLineHeight = m_lineHeight > 0 ? m_lineHeight : MAX(currentLineHeight, charHeight + pCi->top);

	            // get atlas
	            wyTextureAtlas* atlas = (wyTextureAtlas*)wyArrayGet(m_atlasList, pCi->page);

	            // get vertex corner
	            float left = x + lineOffset;
	            float right = left + charWidth;
	            float top = -y - pCi->top;
	            float bottom = top - charHeight;

	            // build vertex
	            wyQuad3D v;
	    		v.bl_x = left;
	    		v.bl_y = bottom;
	    		v.bl_z = 0.0f;
	    		v.br_x = right;
	    		v.br_y = bottom;
	    		v.br_z = 0.0f;
	    		v.tl_x = left;
	    		v.tl_y = top;
	    		v.tl_z = 0.0f;
	    		v.tr_x = right;
	    		v.tr_y = top;
	    		v.tr_z = 0.0f;

	    		// build texture coordinates
	    		wyQuad2D t;
	    		wyTexture2D* tex = m_font->getTexture(pCi->page);
	    	    left = pCi->texRect.x / tex->getPixelWidth();
	    	    right = (pCi->texRect.x + charWidth) / tex->getPixelWidth();
	    	    top = pCi->texRect.y / tex->getPixelHeight();
	    	    bottom = (pCi->texRect.y + charHeight) / tex->getPixelHeight();
	    	    t.bl_x = left;
	    	    t.bl_y = bottom;
	    	    t.br_x = right;
	    	    t.br_y = bottom;
	    	    t.tl_x = left;
	    	    t.tl_y = top;
	    	    t.tr_x = right;
	    	    t.tr_y = top;

	    	    // add quad
	    	    atlas->appendQuad(t, v);

				// adjust x and y
				x += charWidth + pCi->right;
	        } else {
	        	// special check for space or tab
	        	if(c == ' ') {
	        		x += m_spaceWidth;
				} else if(c == '\t') {
	        		x += m_spaceWidth * m_tabSize;
				}
	        }

			// we can clear line first char flag here
			firstLineChar = false;
	    }

		// save line height
		prevLineHeight = currentLineHeight;

		// save max width
		width = MAX(width, x);
	}

	// add last line
	if(prevLineHeight != 0) {
		y += prevLineHeight;
	}

	// set label content size
	setContentSize(width, y);

	// adjust quad
	for(int i = 0; i < m_atlasList->num; i++) {
		wyTextureAtlas* atlas = (wyTextureAtlas*)wyArrayGet(m_atlasList, i);
		atlas->iterateQuad3D(adjustAtlasPosition, this);
	}
	
	// release
	for(vector<const char*>::iterator iter = lines->begin(); iter != lines->end(); iter++) {
		releaseLine(*iter);
	}
	WYDELETE(lines);
	WYDELETE(widthList);
}