示例#1
0
Gwen::Rect Text::GetCharacterPosition( int iChar )
{
	if ( !m_Lines.empty() )
	{
		TextLines::iterator it = m_Lines.begin();
		TextLines::iterator itEnd = m_Lines.end();
		int iChars = 0;

		while ( it != itEnd )
		{
			Text* pLine = *it;
			++it;
			iChars += pLine->Length();

			if ( iChars <= iChar ) { continue; }

			iChars -= pLine->Length();
			Gwen::Rect rect = pLine->GetCharacterPosition( iChar - iChars );
			rect.x += pLine->X();
			rect.y += pLine->Y();
			return rect;
		}
	}

	if ( Length() == 0 || iChar == 0 )
	{
		Gwen::Point p = GetSkin()->GetRender()->MeasureText( GetFont(), L" " );
		return Gwen::Rect( 1, 0, 0, p.y );
	}

	UnicodeString sub = m_String.GetUnicode().substr( 0, iChar );
	Gwen::Point p = GetSkin()->GetRender()->MeasureText( GetFont(), sub );
	return Rect( p.x, 0, 0, p.y );
}
示例#2
0
/// Returns the size required by a call to RenderText if it were to be done now.
Vector2f TextFont::CalculateRenderSizeUnits(Text & text)
{
	if (text.Length() < 1)
	{
		return Vector2f(scale[0], scale[1]);
	}
	// Set starting variables.
	NewText(text);

	// Go up to and include the NULL-sign!
	for (int i = 0; i < text.ArraySize(); ++i)
	{
		currentCharIndex = i;
		currentChar = text.c_str()[i];
		if (currentChar == '\0')
		{
			EndText();
			break;
		}
		nextChar = text.c_str()[i + 1];
		if (EvaluateSpecialChar())
			continue;
		StartChar();
		// RenderChar();
		EndChar();
		lastChar = currentChar;
	}
	return Vector2f (maxRowSizeX, AbsoluteValue(pivotPoint.y));
}
示例#3
0
文件: Text.cpp 项目: r-lyeh/moon9
int Text::GetClosestCharacter( Gwen::Point p )
{
	if ( !m_Lines.empty() )
	{
		TextLines::iterator it = m_Lines.begin();
		TextLines::iterator itEnd = m_Lines.end();
		int iChars = 0;

		while ( it != itEnd )
		{
			Text* pLine = *it;
			++it;

			iChars += pLine->Length();

			if ( p.y < pLine->Y() ) continue;
			if ( p.y > pLine->Bottom() ) continue;

			iChars -= pLine->Length();

			int iLinePos = pLine->GetClosestCharacter( Gwen::Point( p.x - pLine->X(), p.y - pLine->Y() ) );
			//if ( iLinePos > 0 && iLinePos == pLine->Length() ) iLinePos--;
			iLinePos--;

			return iChars + iLinePos;
		}
	}


	int iDistance = 4096;
	int iChar = 0;

	for ( size_t i=0; i<m_String.GetUnicode().length()+1; i++ )
	{
		Gwen::Rect cp = GetCharacterPosition( i );
		int iDist = abs(cp.x - p.x) + abs(cp.y - p.y); // this isn't proper

		if ( iDist > iDistance ) continue;

		iDistance = iDist;
		iChar = i;
	}

	return iChar;
}
示例#4
0
文件: Text.cpp 项目: r-lyeh/moon9
int Text::GetEndCharFromLine( int i )
{
	int iStart = GetStartCharFromLine( i );
	Text* iLine = GetLine( i );

	if ( iLine )
	{
		iStart += iLine->Length();
	}

	return Gwen::Clamp( iStart, 0, Length() );
}
示例#5
0
文件: Text.cpp 项目: r-lyeh/moon9
int Text::GetStartCharFromLine( int i )
{
	TextLines::iterator it = m_Lines.begin();
	TextLines::iterator itEnd = m_Lines.end();
	int iChars = 0;

	while ( it != itEnd )
	{
		Text* pLine = *it;
		++it;
		if ( i == 0 ) return Gwen::Clamp( iChars, 0, Length() );

		iChars += pLine->Length();
		i--;
	}

	return Gwen::Clamp( iChars, 0, Length() );
}
Text KeyCompositionManager::GetComposedKeySym(const Text &t, bool &continueComposing)
{
	Text *tt = (Text *)&t;

	for (int i=0; i<paths->Count(); i++) {
		Text &pathComposition = (*paths)[i]->Composition();
		if (pathComposition.StartsWith(t) && pathComposition.Length() > tt->Length()) {
			continueComposing = true;
			return "";
		} else if (pathComposition == t) {
			continueComposing = false;
			return (*paths)[i]->Result();
		}
	}
	
	continueComposing = false;
	return t;
}
示例#7
0
文件: Text.cpp 项目: r-lyeh/moon9
int Text::GetLineFromChar( int i )
{
	TextLines::iterator it = m_Lines.begin();
	TextLines::iterator itEnd = m_Lines.end();
	int iChars = 0;
	int iLine = 0;

	while ( it != itEnd )
	{
		Text* pLine = *it;
		++it;

		iChars += pLine->Length();

		if ( iChars > i ) return iLine;
		iLine++;
	}

	return iLine;
}
already_AddRefed<XPathResult>
XPathExpression::EvaluateWithContext(nsINode& aContextNode,
                                     uint32_t aContextPosition,
                                     uint32_t aContextSize,
                                     uint16_t aType,
                                     XPathResult* aInResult,
                                     ErrorResult& aRv)
{
    if (aContextPosition > aContextSize) {
        aRv.Throw(NS_ERROR_FAILURE);
        return nullptr;
    }

    if (aType > XPathResult_Binding::FIRST_ORDERED_NODE_TYPE) {
        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
        return nullptr;
    }

    if (!nsContentUtils::LegacyIsCallerNativeCode() &&
        !nsContentUtils::CanCallerAccess(&aContextNode))
    {
        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
        return nullptr;
    }

    if (mCheckDocument) {
        nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
        if (doc != aContextNode.OwnerDoc()) {
            aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
            return nullptr;
        }
    }

    uint16_t nodeType = aContextNode.NodeType();

    if (nodeType == nsINode::TEXT_NODE ||
        nodeType == nsINode::CDATA_SECTION_NODE) {
        Text* textNode = aContextNode.GetAsText();
        MOZ_ASSERT(textNode);

        uint32_t textLength = textNode->Length();
        if (textLength == 0) {
            aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
            return nullptr;
        }

        // XXX Need to get logical XPath text node for CDATASection
        //     and Text nodes.
    }
    else if (nodeType != nsINode::DOCUMENT_NODE &&
             nodeType != nsINode::ELEMENT_NODE &&
             nodeType != nsINode::ATTRIBUTE_NODE &&
             nodeType != nsINode::COMMENT_NODE &&
             nodeType != nsINode::PROCESSING_INSTRUCTION_NODE) {
        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
        return nullptr;
    }

    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
    if (!contextNode) {
      aRv.Throw(NS_ERROR_FAILURE);
      return nullptr;
    }

    EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
                             mRecycler);
    RefPtr<txAExprResult> exprResult;
    aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
    if (aRv.Failed()) {
        return nullptr;
    }

    uint16_t resultType = aType;
    if (aType == XPathResult::ANY_TYPE) {
        short exprResultType = exprResult->getResultType();
        switch (exprResultType) {
            case txAExprResult::NUMBER:
                resultType = XPathResult::NUMBER_TYPE;
                break;
            case txAExprResult::STRING:
                resultType = XPathResult::STRING_TYPE;
                break;
            case txAExprResult::BOOLEAN:
                resultType = XPathResult::BOOLEAN_TYPE;
                break;
            case txAExprResult::NODESET:
                resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
                break;
            case txAExprResult::RESULT_TREE_FRAGMENT:
                aRv.Throw(NS_ERROR_FAILURE);
                return nullptr;
        }
    }

    RefPtr<XPathResult> xpathResult = aInResult;
    if (!xpathResult) {
        xpathResult = new XPathResult(&aContextNode);
    }

    aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode);

    return xpathResult.forget();
}
void GlyphsSelection::AcceptKey(string_slice key, DisplayDirector* director)
{
	int offset;

	if (tagEditor || key == "\t")
		TagSelection::AcceptKey(key, director);
	else if (key == "\n") {
		// not supported yet
		/***/
		}
	else if (key == Keys::LeftArrowKey) {
		offset = firstGlyph.textNode->OffsetOfGlyph(firstGlyph.glyph);
		director->SetSelection(firstGlyph.textNode->GetSelectionAtOffset(offset));
		director->ScrollToSelection();
		}
	else if (key == Keys::RightArrowKey) {
		offset = lastGlyph.textNode->OffsetOfGlyph(lastGlyph.glyph) +
			lastGlyph.glyph->NumCharsInText();
		director->SetSelection(lastGlyph.textNode->GetSelectionAtOffset(offset));
		director->ScrollToSelection();
		}
	else {
		String newText = key;
		if (key == "\b" || key == Keys::DelKey)
			newText = "";
		ReplaceText(newText, director);
#ifdef NOT_ANYMORE
		// set up
		DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
		if (ancestor == NULL)
			throw InternalException("GlyphsSelection::AcceptKey: No common ancestor.");
		bool hasFirstText = (firstGlyph.textNode->Parent() == ancestor);
		bool hasLastText = (lastGlyph.textNode->Parent() == ancestor);
		bool oneText = (firstGlyph.textNode == lastGlyph.textNode);
		bool hasNodes =
			(!oneText &&
				(!hasFirstText || !hasLastText ||
				 firstGlyph.textNode->NextSibling() != firstGlyph.textNode));
		CompositeAction* action = new CompositeAction();
		action->AddAction(new RestoreGlyphsSelectionAction());
		// clear out anything that's there
		if (oneText) {
			unsigned long startOffset = firstGlyph.StartOffset();
			action->AddAction(new DeleteCharsAction(firstGlyph.textNode->GetText(),
			                                        startOffset,
			                                        lastGlyph.EndOffset() - startOffset));
			}
		else {
			if (hasFirstText) {
				Text* firstText = firstGlyph.textNode->GetText();
				unsigned long offset = firstGlyph.StartOffset();
				action->AddAction(new DeleteCharsAction(firstText, offset,
				                                        firstText->Length() - offset));
				}
			if (hasLastText) {
				action->AddAction(new DeleteCharsAction(lastGlyph.textNode->GetText(),
				                                        0, lastGlyph.EndOffset()));
				}
			if (hasNodes) {
				ElementDisplayNode* ancestorDisplayNode = dynamic_cast<ElementDisplayNode*>(ancestor);
				if (ancestorDisplayNode == NULL)
					throw InternalException("GlyphsSelection::AcceptKey: ancestor isn't an element.");
				Element* ancestorElement = ancestorDisplayNode->GetElement();
				Node* firstDeleteNode = firstGlyph.textNode->GetText();
				while (firstDeleteNode->ParentNode() != ancestorElement)
					firstDeleteNode = firstDeleteNode->ParentNode();
				if (hasFirstText)
					firstDeleteNode = firstDeleteNode->NextSibling();
				Node* lastDeleteNode = lastGlyph.textNode->GetText();
				while (lastDeleteNode->ParentNode() != ancestorElement)
					lastDeleteNode = lastDeleteNode->ParentNode();
				if (hasLastText)
					lastDeleteNode = lastDeleteNode->PreviousSibling();
				action->AddAction(new RemoveNodesAction(firstDeleteNode, lastDeleteNode));
				}
			}
		// add in the key
		if (key == "\b" || key == Keys::DelKey) {
			// just select
			Text* selectText = NULL;
			unsigned long selectOffset = 0;
			if (oneText || hasFirstText) {
				selectText = firstGlyph.textNode->GetText();
				selectOffset = firstGlyph.StartOffset();
				}
			else if (hasLastText) {
				selectText = lastGlyph.textNode->GetText();
				selectOffset = 0;
				}
			else {
				// we don't handle this yet (point selection between two Elements)
				/***/
				}
			if (selectText)
				action->AddAction(new SelectPointAction(selectText, selectOffset));
			}
		else {
			Text* destText;
			unsigned long destOffset;
			if (oneText || hasFirstText) {
				destText = firstGlyph.textNode->GetText();
				destOffset = firstGlyph.StartOffset();
				}
			else if (hasLastText) {
				destText = lastGlyph.textNode->GetText();
				destOffset = 0;
				}
			else {
				NewTextAction* newTextAction =
					new NewTextAction(firstGlyph.textNode->GetText()->OwnerDocument());
				action->AddAction(newTextAction);
				destText = newTextAction->GetText();
				destOffset = 0;
				}
			action->AddAction(new AddCharsAction(key, destText, destOffset));
				// this will do the selection also
			}
		// go!
		director->DoAction(action);
#endif
		}
}
void GlyphsSelection::ReplaceText(String newText, DisplayDirector* director)
{
	// set up
	DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
	if (ancestor == NULL)
		throw InternalException("GlyphsSelection::AcceptKey: No common ancestor.");
	bool hasFirstText = (firstGlyph.textNode->Parent() == ancestor);
	bool hasLastText = (lastGlyph.textNode->Parent() == ancestor);
	bool oneText = (firstGlyph.textNode == lastGlyph.textNode);
	bool hasNodes =
		(!oneText &&
			(!hasFirstText || !hasLastText ||
			 firstGlyph.textNode->NextSibling() != firstGlyph.textNode));
	CompositeAction* action = new CompositeAction();
	action->AddAction(new RestoreGlyphsSelectionAction());

	// clear out anything that's there
	if (oneText) {
		unsigned long startOffset = firstGlyph.StartOffset();
		action->AddAction(new DeleteCharsAction(firstGlyph.textNode->GetText(),
		                                        startOffset,
		                                        lastGlyph.EndOffset() - startOffset));
		}
	else {
		if (hasFirstText) {
			Text* firstText = firstGlyph.textNode->GetText();
			unsigned long offset = firstGlyph.StartOffset();
			action->AddAction(new DeleteCharsAction(firstText, offset,
			                                        firstText->Length() - offset));
			}
		if (hasLastText) {
			action->AddAction(new DeleteCharsAction(lastGlyph.textNode->GetText(),
			                                        0, lastGlyph.EndOffset()));
			}
		if (hasNodes) {
			ElementDisplayNode* ancestorDisplayNode = dynamic_cast<ElementDisplayNode*>(ancestor);
			if (ancestorDisplayNode == NULL)
				throw InternalException("GlyphsSelection::AcceptKey: ancestor isn't an element.");
			Element* ancestorElement = ancestorDisplayNode->GetElement();
			Node* firstDeleteNode = firstGlyph.textNode->GetText();
			while (firstDeleteNode->ParentNode() != ancestorElement)
				firstDeleteNode = firstDeleteNode->ParentNode();
			if (hasFirstText)
				firstDeleteNode = firstDeleteNode->NextSibling();
			Node* lastDeleteNode = lastGlyph.textNode->GetText();
			while (lastDeleteNode->ParentNode() != ancestorElement)
				lastDeleteNode = lastDeleteNode->ParentNode();
			if (hasLastText)
				lastDeleteNode = lastDeleteNode->PreviousSibling();
			action->AddAction(new RemoveNodesAction(firstDeleteNode, lastDeleteNode));
			}
		}

	// if we're replacing it with nothing, just select the point
	if (newText.empty()) {
		// just select
		Text* selectText = NULL;
		unsigned long selectOffset = 0;
		if (oneText || hasFirstText) {
			selectText = firstGlyph.textNode->GetText();
			selectOffset = firstGlyph.StartOffset();
			}
		else if (hasLastText) {
			selectText = lastGlyph.textNode->GetText();
			selectOffset = 0;
			}
		else {
			// we don't handle this yet (point selection between two Elements)
			/***/
			}
		if (selectText)
			action->AddAction(new SelectPointAction(selectText, selectOffset));
		}

	// add in the new text
	else {
		Text* destText;
		unsigned long destOffset;
		if (oneText || hasFirstText) {
			destText = firstGlyph.textNode->GetText();
			destOffset = firstGlyph.StartOffset();
			}
		else if (hasLastText) {
			destText = lastGlyph.textNode->GetText();
			destOffset = 0;
			}
		else {
			NewTextAction* newTextAction =
				new NewTextAction(firstGlyph.textNode->GetText()->OwnerDocument());
			action->AddAction(newTextAction);
			destText = newTextAction->GetText();
			destOffset = 0;
			}
		action->AddAction(new AddCharsAction(newText, destText, destOffset));
			// this will do the selection also
		}

	// do it
	director->DoAction(action);
}
String GlyphsSelection::GetXMLCopy()
{
	// handle single-text case
	bool singleText = (firstGlyph.textNode == lastGlyph.textNode);
	if (singleText) {
		int startOffset = firstGlyph.StartOffset();
		int endOffset = lastGlyph.EndOffset();
		return firstGlyph.textNode->GetText()->SubstringData(startOffset, endOffset - startOffset);
		}

	// get info about the structure
	DisplayNode* ancestor = firstGlyph.CommonAncestorWith(lastGlyph);
	bool startsWithText = (firstGlyph.textNode->Parent() == ancestor);
	bool endsWithText = (lastGlyph.textNode->Parent() == ancestor);

	// find out where the first and last embedded elements are
	// first
	ElementDisplayNode* firstElementDisplayNode = NULL;
	if (!startsWithText) {
		// it's the element the first glyph is in
		DisplayNode* firstElementNode = firstGlyph.textNode;
		while (firstElementNode) {
			if (firstElementNode->Parent() == ancestor)
				break;
			firstElementNode = firstElementNode->Parent();
			}
		firstElementDisplayNode = dynamic_cast<ElementDisplayNode*>(firstElementNode);
		}
	else {
		firstElementDisplayNode =
			dynamic_cast<ElementDisplayNode*>(firstGlyph.textNode->NextSibling());
		}
	if (firstElementDisplayNode == NULL)
		throw InternalException("GlyphsSelection::GetXMLCopy: Couldn't find firstElementNode.");
	Node* firstElement = firstElementDisplayNode->GetElement();
	// last
	ElementDisplayNode* lastElementDisplayNode = NULL;
	if (!endsWithText) {
		// it's the element the last glyph is in
		DisplayNode* lastElementNode = lastGlyph.textNode;
		while (lastElementNode) {
			if (lastElementNode->Parent() == ancestor)
				break;
			lastElementNode = lastElementNode->Parent();
			}
		lastElementDisplayNode = dynamic_cast<ElementDisplayNode*>(lastElementNode);
		}
	else {
		lastElementDisplayNode =
			dynamic_cast<ElementDisplayNode*>(lastGlyph.textNode->PreviousSibling());
		}
	if (lastElementDisplayNode == NULL)
		throw InternalException("GlyphsSelection::GetXMLCopy: Couldn't find lastElementNode.");
	Node* lastElement = lastElementDisplayNode->GetElement();

	// write the selection
	XMLStringWriter writer(NULL);
	if (startsWithText) {
		Text* startText = firstGlyph.textNode->GetText();
		int startOffset = firstGlyph.StartOffset();
		String startData =
			startText->SubstringData(startOffset, startText->Length() - startOffset);
		writer.AppendString(startData);
		}
	for (Node* node = firstElement; ; node = node->NextSibling()) {
		writer.AppendNode(node);
		if (node == lastElement)
			break;
		}
	if (endsWithText) {
		Text* endText = lastGlyph.textNode->GetText();
		int endOffset = lastGlyph.EndOffset();
		String endData = endText->SubstringData(0, endOffset);
		writer.AppendString(endData);
		}
	return writer.GetString();
}
示例#12
0
/// Renders text ^^
void TextFont::RenderText(Text & text, GraphicsState & graphicsState)
{
	// Set starting variables.
	NewText(text);

	/// One color for all text?
	this->SetColor(text.color);
	
	/// Save old shader!
	Shader * oldShader = ActiveShader();
	// Load shader, set default uniform values, etc.
	if (!PrepareForRender())
		return;

	/// Sort the carets in order to render selected text properly.
	int min, max;
	if (text.caretPosition < text.previousCaretPosition)
	{
		min = text.caretPosition;
		max = text.previousCaretPosition;
	}
	else 
	{
		max = text.caretPosition;
		min = text.previousCaretPosition;
	}

	bool shouldRenderCaret = Timer::GetCurrentTimeMs() % 1000 > 500;
	if (text.Length() == 0 && shouldRenderCaret)
		RenderChar('|');
	for (i = 0; i < text.Length(); ++i)
	{
		if (text.caretPosition == i && shouldRenderCaret)
		{
			RenderChar('|');
		}
		currentCharIndex = i;
		currentChar = text.c_str()[i];
		if (currentChar == 0)
			break;
		nextChar = text.c_str()[i + 1];

		if (EvaluateSpecialChar())
			continue;

		StartChar();				// Move in.
		RenderChar(currentChar);	// Render
		/// If we are between the 2 active carets, render the region the char covers over with a white quad ?
		if (text.previousCaretPosition != -1 && i >= min && i < max)
		{
			RenderSelection(currentChar);			
		}
		EndChar();					// Move out.
		lastChar = currentChar;
	}
	// Caret at the end?
	if (text.caretPosition >= text.Length() && shouldRenderCaret)
	{
		RenderChar('|');
	}
	
	OnEndRender(graphicsState);
	/// Revert to old shader!
	ShadeMan.SetActiveShader(oldShader);
}