void Font::drawString(Surface *dst, const Common::String &str, int x, int y, int with_color, int spacing, bool markDirty) const { assert(dst != NULL); assert(x >= 0); assert(y >= 0); uint widest = getStringWidth(str, spacing); int curx = x + (widest - getLineWidth(str, 0, spacing)) / 2; int cury = y; for (uint i = 0; i < str.size(); ++i) { // If we encounter the '|' char (newline and end of string marker), // skip it and go to the start of the next line if (str[i] == '|') { cury += getFontHeight(); curx = x + (widest - getLineWidth(str, i+1, spacing) - 1) / 2; continue; } // Break early if there's no more space on the screen if (curx >= dst->w - 1 || cury >= dst->h - 1) { break; } drawChar(dst, str[i], curx, cury, with_color); curx += getCharWidth(str[i]) + spacing; } if (markDirty) { Common::Rect r(x, y, x + widest, y + getStringHeight(str)); dst->markDirtyRect(r); } }
void MacText::render(int from, int to) { reallocSurface(); from = MAX<int>(0, from); to = MIN<int>(to, _textLines.size() - 1); // Clear the screen _surface->fillRect(Common::Rect(0, _textLines[from].y, _surface->w, _textLines[to].y + getLineHeight(to)), _bgcolor); for (int i = from; i <= to; i++) { int xOffset = 0; if (_textAlignment == kTextAlignRight) xOffset = _textMaxWidth - getLineWidth(i); else if (_textAlignment == kTextAlignCenter) xOffset = (_textMaxWidth / 2) - (getLineWidth(i) / 2); // TODO: _textMaxWidth, when -1, was not rendering ANY text. for (uint j = 0; j < _textLines[i].chunks.size(); j++) { if (_textLines[i].chunks[j].text.empty()) continue; _textLines[i].chunks[j].getFont()->drawString(_surface, _textLines[i].chunks[j].text, xOffset, _textLines[i].y, _maxWidth, _fgcolor); xOffset += _textLines[i].chunks[j].getFont()->getStringWidth(_textLines[i].chunks[j].text); } } for (uint i = 0; i < _textLines.size(); i++) { debugN(4, "%2d ", i); for (uint j = 0; j < _textLines[i].chunks.size(); j++) debugN(4, "[%d (%d)] \"%s\" ", _textLines[i].chunks[j].fontId, _textLines[i].chunks[j].textSlant, _textLines[i].chunks[j].text.c_str()); debug(4, "%s", ""); } }
int MacText::getLineHeight(int line) { if ((uint)line >= _textLines.size()) return 0; getLineWidth(line); // This calculates height also return _textLines[line].height; }
uint FontHelper::getTextWidth(const string& text) { if (text.find("\n",0)!=string::npos) { vector<string> textArr; split(textArr,text,"\n"); return getTextWidth(&textArr); } else return getLineWidth(text); }
void LineLayer::setLineWidth(DataDrivenPropertyValue<float> value) { if (value == getLineWidth()) return; auto impl_ = mutableImpl(); impl_->paint.template get<LineWidth>().value = value; baseImpl = std::move(impl_); observer->onLayerChanged(*this); }
void RectangleTool::mouseDown(struct point2f p) { Tool::mouseDown(p); rect = new Rectangle(filled); rect->setColor(getColor()); rect->setLineWidth(getLineWidth()); rect->setStart(p); rect->setEnd(p); notifyIntermediatePaintableCreated(rect); }
void LinePath::growList(LineList &list, int by) { QPen pen( getLineColor(), getLineWidth() ); for (int i = 0; i < by; i++) { QCanvasLine * line = new QCanvasLine( getCanvas() ); line -> setZ( 0 ); line -> setPen( pen ); line -> setVisible( true ); list.append( line ); } }
FX_BOOL CFX_QuartzDeviceDriver::DrawPath(const CFX_PathData* pathData, const CFX_AffineMatrix* matrix, const CFX_GraphStateData* graphState, FX_DWORD fillArgb, FX_DWORD strokeArgb, int fillMode, int alpha_flag, void* pIccTransform, int blend_type ) { SaveState(); CGBlendMode mode = GetCGBlendMode(blend_type); if (mode != kCGBlendModeNormal) { CGContextSetBlendMode(_context, mode); } CGAffineTransform m = CGAffineTransformIdentity; if (matrix) { m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(), matrix->GetE(), matrix->GetF()); } m = CGAffineTransformConcat(m, _foxitDevice2User); CGContextConcatCTM(_context, m); int pathMode = 0; if (graphState && strokeArgb) { CGContextSetMiterLimit(_context, graphState->m_MiterLimit); FX_FLOAT lineWidth = getLineWidth(graphState, m); setStrokeInfo(graphState, strokeArgb, lineWidth); pathMode |= 4; } if (fillMode && fillArgb) { setFillInfo(fillArgb); if ((fillMode & 3) == FXFILL_WINDING) { pathMode |= 1; } else if ((fillMode & 3) == FXFILL_ALTERNATE) { pathMode |= 2; } } setPathToContext(pathData); if (fillMode & FXFILL_FULLCOVER) { CGContextSetShouldAntialias(_context, false); } if (pathMode == 4) { CGContextStrokePath(_context); } else if (pathMode == 1) { CGContextFillPath(_context); } else if (pathMode == 2) { CGContextEOFillPath(_context); } else if (pathMode == 5) { CGContextDrawPath(_context, kCGPathFillStroke); } else if (pathMode == 6) { CGContextDrawPath(_context, kCGPathEOFillStroke); } RestoreState(FALSE); return TRUE; }
void MacText::recalcDims() { int y = 0; _textMaxWidth = 0; for (uint i = 0; i < _textLines.size(); i++) { _textLines[i].y = y; y += getLineHeight(i) + _interLinear; _textMaxWidth = MAX(_textMaxWidth, getLineWidth(i, true)); } _textMaxHeight = y - _interLinear; }
void GDrawingSurface::initializeGObject(GObject* obj, bool fill) { if (!obj) { return; } obj->setColor(getColor()); if (fill) { obj->setFilled(true); obj->setFillColor(getFillColor()); } obj->setFont(getFont()); obj->setLineStyle(getLineStyle()); obj->setLineWidth(getLineWidth()); }
/* PUBLIC MEMBER FUNCTIONS */ void CueButton::render(void) { Button::render(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(position.getX(), position.getY(), 0.0f); saveTransform(); glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); glLineWidth(getLineWidth(ICON_LINE_WIDTH)); if(cueButtonDirty) { glNewList(cueButtonDisplayList, GL_COMPILE); // box glLineWidth(1.0f); glEnable(GL_LINE_SMOOTH); for(unsigned int i = 0; i < 2; i++) { float renderOpacity = (i == 0) ? 1.0f : 1.0f; glColor4f(1.0f, 1.0f, 1.0f, renderOpacity); GLenum renderMode = (i == 0) ? GL_QUADS : GL_LINE_LOOP; glBegin(renderMode); glVertex3f(width * 0.4f, height * 0.7f, 0.0f); glVertex3f(width * 0.8f, height * 0.7f, 0.0f); glVertex3f(width * 0.8f, height * 0.3f, 0.0f); glVertex3f(width * 0.4f, height * 0.3f, 0.0f); glEnd(); renderMode = (i == 0) ? GL_TRIANGLES : GL_LINE_LOOP; glBegin(renderMode); glVertex3f(width * 0.2f, height * 0.7f, 0.0f); glVertex3f(width * 0.4f, height * 0.5f, 0.0f); glVertex3f(width * 0.2f, height * 0.3f, 0.0f); glEnd(); } glDisable(GL_LINE_SMOOTH); glEndList(); cueButtonDirty = false; } glCallList(cueButtonDisplayList); glPopAttrib(); glPopMatrix(); }
void LineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, int& propertyCount, OctreeElement::AppendState& appendState) const { bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth()); APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints()); }
bool LineLayer::Impl::queryIntersectsGeometry( const GeometryCollection& queryGeometry, const GeometryCollection& geometry, const float bearing, const float pixelsToTileUnits) const { const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits; auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits); auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits); return util::multiPolygonIntersectsBufferedMultiLine( translatedQueryGeometry.value_or(queryGeometry), offsetGeometry.value_or(geometry), halfWidth); }
//----------------------------------------------------------------------------- void D2DDrawContext::drawGraphicsPath (CGraphicsPath* _path, PathDrawMode mode, CGraphicsTransform* t) { if (renderTarget == 0) return; D2DGraphicsPath* d2dPath = dynamic_cast<D2DGraphicsPath*> (_path); if (d2dPath == 0) return; ID2D1PathGeometry* path = d2dPath->getPath (mode == kPathFilledEvenOdd ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING); if (path) { D2DApplyClip ac (this); ID2D1Geometry* geometry = 0; if (t) { ID2D1TransformedGeometry* tg = 0; D2D1_MATRIX_3X2_F matrix; matrix._11 = (FLOAT)t->m11; matrix._12 = (FLOAT)t->m12; matrix._21 = (FLOAT)t->m21; matrix._22 = (FLOAT)t->m22; matrix._31 = (FLOAT)t->dx; matrix._32 = (FLOAT)t->dy; getD2DFactory ()->CreateTransformedGeometry (path, matrix, &tg); geometry = tg; } else { geometry = path; geometry->AddRef (); } getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Translation ((FLOAT)getOffset ().x, (FLOAT)getOffset ().y)); if (mode == kPathFilled || mode == kPathFilledEvenOdd) getRenderTarget ()->FillGeometry (geometry, getFillBrush ()); else if (mode == kPathStroked) getRenderTarget ()->DrawGeometry (geometry, getStrokeBrush (), (FLOAT)getLineWidth (), getStrokeStyle ()); getRenderTarget ()->SetTransform (D2D1::Matrix3x2F::Identity ()); geometry->Release (); } }
void LinePath::createHeadLines() { m_HeadList.clear(); QCanvas * canvas = getCanvas(); switch( getAssocType() ) { case Uml::at_Activity: case Uml::at_State: case Uml::at_Dependency: case Uml::at_UniAssociation: case Uml::at_Relationship: growList(m_HeadList, 2); break; case Uml::at_Generalization: case Uml::at_Realization: growList(m_HeadList, 3); m_pClearPoly = new QCanvasPolygon( canvas ); m_pClearPoly -> setVisible( true ); m_pClearPoly -> setBrush( QBrush( Qt::white ) ); m_pClearPoly -> setZ( -1 ); break; case Uml::at_Composition: case Uml::at_Aggregation: growList(m_HeadList, 4); m_pClearPoly = new QCanvasPolygon( canvas ); m_pClearPoly -> setVisible( true ); if( getAssocType() == Uml::at_Aggregation ) m_pClearPoly -> setBrush( QBrush( Qt::white ) ); else m_pClearPoly -> setBrush( QBrush( getLineColor() ) ); m_pClearPoly -> setZ( -1 ); break; case Uml::at_Containment: growList(m_HeadList, 1); if (!m_pCircle) { m_pCircle = new Circle( canvas, 6 ); m_pCircle->show(); m_pCircle->setPen( QPen( getLineColor(), getLineWidth() ) ); } break; default: break; } m_bHeadCreated = true; }
FX_BOOL CFX_QuartzDeviceDriver::SetClip_PathStroke(const CFX_PathData* pathData, const CFX_AffineMatrix* matrix, const CFX_GraphStateData* graphState ) { SaveState(); CGAffineTransform m = CGAffineTransformIdentity; if (matrix) { m = CGAffineTransformMake(matrix->GetA(), matrix->GetB(), matrix->GetC(), matrix->GetD(), matrix->GetE(), matrix->GetF()); } m = CGAffineTransformConcat(m, _foxitDevice2User); CGContextConcatCTM(_context, m); FX_FLOAT lineWidth = getLineWidth(graphState, m); setStrokeInfo(graphState, 0xFF000000, lineWidth); setPathToContext(pathData); CGContextReplacePathWithStrokedPath(_context); RestoreState(FALSE); CGContextClip(_context); return TRUE; }
void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, int& propertyCount, OctreeElement::AppendState& appendState) const { QWriteLocker lock(&_quadReadWriteLock); bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth()); APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints()); APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals()); APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors()); APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, getIsUVModeStretch()); }
void RenderableLineEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RenderableLineEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Line); updateGeometry(); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; Transform transform = Transform(); transform.setTranslation(getPosition()); transform.setRotation(getRotation()); batch.setModelTransform(transform); batch._glLineWidth(getLineWidth()); if (getLinePoints().size() > 1) { DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch); DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); } batch._glLineWidth(1.0f); RenderableDebugableEntityItem::render(this, args); };
void FFTSplineControl::renderSplineControl(float splineControlWidth) { glPushAttrib(GL_LINE_BIT | GL_CURRENT_BIT); glColor4f(1.0f, 1.0f, 1.0, 1.0f); glLineWidth(getLineWidth(1.0f)); glEnable(GL_LINE_SMOOTH); glBegin(GL_LINE_STRIP); float increment = InterfaceManager::getBeatLength() / (float)InterfaceManager::VALUES_PER_BEAT; for(float f = 0.0; f <= splineControlWidth; f+= (increment / (float)UPSAMPLE_FACTOR)) { float legendlessHeight = height - ((height * LEGEND_DIM) * 2.0f); float value = getValue(f); float vx = f; float vy = (value * legendlessHeight) + (height * LEGEND_DIM); glVertex3f(vx, height - vy, 0.0f); } glEnd(); glDisable(GL_LINE_SMOOTH); glPopAttrib(); }
//----------------------------------------------------------------------------- void D2DDrawContext::drawGraphicsPath (CGraphicsPath* _path, PathDrawMode mode, CGraphicsTransform* t) { if (renderTarget == 0) return; bool halfPointOffset = (mode == kPathStroked || currentState.drawMode.integralMode ()) ? ((((int32_t)currentState.frameWidth) % 2) != 0) : false; D2DApplyClip ac (this, halfPointOffset); if (ac.isEmpty ()) return; D2DGraphicsPath* d2dPath = dynamic_cast<D2DGraphicsPath*> (_path); if (d2dPath == 0) return; ID2D1Geometry* path = d2dPath->createPath (mode == kPathFilledEvenOdd ? D2D1_FILL_MODE_ALTERNATE : D2D1_FILL_MODE_WINDING, currentState.drawMode.integralMode () ? this : 0, t); if (path) { if (mode == kPathFilled || mode == kPathFilledEvenOdd) getRenderTarget ()->FillGeometry (path, getFillBrush ()); else if (mode == kPathStroked) getRenderTarget ()->DrawGeometry (path, getStrokeBrush (), (FLOAT)getLineWidth (), getStrokeStyle ()); path->Release (); } }
void QLineItem::compile(QSqlDatabase &db, int nSceneId,int &count,int index) { count++; //QBasicGraphicsItem::compile(db, nSceneId, count, index); QSqlQuery sqlquery(db); sqlquery.prepare("INSERT INTO line(nItemNumber ,nSceneId ,eLineClass ,eLineType ,nLineWidth ," "nLineColor ,eLineArrow ,nAlpha , eLinePointType ,nZvalue,nCollidindId," "nStartX ,nStartY ,nWidth ,nHeight )" "VALUES (:nItemNumber ,:nSceneId ,:eLineClass ,:eLineType ,:nLineWidth ," ":nLineColor ,:eLineArrow ,:nAlpha , :eLinePointType,:nZvalue,:nCollidindId," ":nStartX ,:nStartY ,:nWidth ,:nHeight)"); sqlquery.bindValue(":nItemNumber",QVariant(count));// 表 id sqlquery.bindValue(":nSceneId",QVariant(nSceneId));// 所在场景 id sqlquery.bindValue(":eLineClass",QVariant(1)); //1 代表类型为直线 sqlquery.bindValue(":eLineType",QVariant(nLineType+1));// 线形 sqlquery.bindValue(":nLineWidth",QVariant(getLineWidth()));// 线宽 sqlquery.bindValue(":nLineColor",QVariant(ColorToInt(getLineColor()))); //颜色 sqlquery.bindValue(":eLineArrow",QVariant(m_eLineEndArrowType+1));// 箭头 sqlquery.bindValue(":nAlpha",QVariant(getAlpha()));// 透明度 sqlquery.bindValue(":eLinePointType",QVariant(m_eLineEndArrowType+1)); //端点类型 sqlquery.bindValue(":nZvalue",QVariant(zValue()));//层次 sqlquery.bindValue(":nCollidindId",QVariant(index));//碰撞ID QRectF rect = sceneBoundingRect(); if(getLineWidth() == 1) { sqlquery.bindValue(":nStartX",QVariant(rect.x()-1));//x sqlquery.bindValue(":nStartY",QVariant(rect.y()-1));//y sqlquery.bindValue(":nWidth",QVariant(rect.width()+2));//w sqlquery.bindValue(":nHeight",QVariant(rect.height()+2));//h } else { sqlquery.bindValue(":nStartX",QVariant(rect.x()));//x sqlquery.bindValue(":nStartY",QVariant(rect.y()));//y sqlquery.bindValue(":nWidth",QVariant(rect.width()));//w sqlquery.bindValue(":nHeight",QVariant(rect.height()));//h } bool result = false; result = sqlquery.exec(); qDebug() << "insert line table :"<<result; sqlquery.prepare("INSERT INTO point(nItemId,nPosX,nPosY,nOrder,ePointType)" "VALUES (:nItemId ,:nPosX ,:nPosY ,:nOrder ,:ePointType )"); for(int i=0; i<2; i++) { QPointF pt = this->path().pointAtPercent(i); pt = mapToScene(pt); sqlquery.bindValue(":nItemId",QVariant(count));// item表 id sqlquery.bindValue(":nPosX",QVariant((int)pt.x()));// X sqlquery.bindValue(":nPosY",QVariant((int)pt.y())); //Y sqlquery.bindValue(":nOrder",QVariant(i));// 顺序 sqlquery.bindValue(":ePointType",QVariant(1));// 显示点 result = sqlquery.exec(); qDebug() << "insert point table :"<<result; } SamDrawScene *pScene = dynamic_cast<SamDrawScene *>(scene()); if(pScene && pScene->nIsSceneOrWindow == 2) { //是自定义键盘的item //先新建键盘——item关联表 item表在派生类中创建 //QSqlQuery sqlquery(db); sqlquery.prepare("INSERT INTO kbAndItem(nKeyBoardId , nItemId ,nId,nItemTableType ) " "VALUES (:nKeyBoardId ,:nItemId ,:nId,:nItemTableType)"); sqlquery.bindValue(":nKeyBoardId",QVariant(nSceneId)); sqlquery.bindValue(":nItemId",QVariant(count)); sqlquery.bindValue(":nId",QVariant(id())); sqlquery.bindValue(":nItemTableType",QVariant((int)SAM_DRAW_OBJECT_LINE)); bool result = false; result = sqlquery.exec(); qDebug() << "insert kbAndItem table :"<<result; } if(pScene && pScene->nIsSceneOrWindow != 2) { //窗口或者场景item //先新建键盘——item关联表 //item表在派生类中创建 //QSqlQuery sqlquery(db); sqlquery.prepare("INSERT INTO sceneAndItem(nSceneId,nItemId,nId,nItemTableType)" "VALUES(:nSceneId,:nItemId,:nId,:nItemTableType)"); sqlquery.bindValue(":nSceneId",QVariant(nSceneId)); sqlquery.bindValue(":nItemId",QVariant(count)); sqlquery.bindValue(":nId",QVariant(id())); //int t = this->GroupType(); sqlquery.bindValue(":nItemTableType",QVariant((int)SAM_DRAW_OBJECT_LINE)); bool result = false; result = sqlquery.exec(); qDebug() << "insert sceneAndItem table :"<<result; } }
void SimpleTypeLayout::getGlyphLayout (const AttributedString& text, GlyphLayout& glyphLayout) { clear(); int stringLength = text.getText().length(); int numCharacterAttributes = text.getCharAttributesSize(); int rangeStart = 0; // Character attributes are applied as a series of ranges. These ranges may overlap or there may // be multiple attributes for the same range. We need to come up with a single set of unique and // non overlapping ranges. // The approach below iterates through every character, looks through all the attributes and their // ranges and stores the last font or color that was applied. It think constructs a set of unique // and non overlapping ranges by comparing each character's attributes to the previous characters // attributes. // A more efficient approach may be to split and combine the individual ranges to construct the // set of unique and non overlapping ranges. This more efficient approach, if possible, would only // need to iterate through all the attributes once. This would be much faster than the current // approach which loops through all the attributes for every character. Font defaultFont; Colour defaultColour (Colours::black); Array<RunAttribute> runAttributes; Array<CharAttribute> charAttributes; charAttributes.ensureStorageAllocated (stringLength); // Iterate through every character in the string for (int i = 0; i < stringLength; ++i) { CharAttribute attribute; attribute.font = &defaultFont; attribute.colour = &defaultColour; // Iterate through every character attribute for (int j = 0; j < numCharacterAttributes; ++j) { Attr* attr = text.getCharAttribute (j); // Check if the current character falls within the range of a font attribute if (attr->attribute == Attr::font && (i >= attr->range.getStart()) && (i < attr->range.getEnd())) { AttrFont* attrFont = static_cast<AttrFont*>(attr); attribute.font = &(attrFont->font); } // Check if the current character falls within the range of a foreground colour attribute if (attr->attribute == Attr::foregroundColour && (i >= attr->range.getStart()) && (i < attr->range.getEnd())) { AttrColour* attrColour = static_cast<AttrColour*>(attr); attribute.colour = &(attrColour->colour); } } charAttributes.add(attribute); // Skip the first character since we are comparing to previous characters if (i == 0) continue; if ((charAttributes[i-1].font != charAttributes[i].font) || (charAttributes[i-1].colour != charAttributes[i].colour) || (*(charAttributes[i-1].font) != *(charAttributes[i].font)) || (*(charAttributes[i-1].colour) != *(charAttributes[i].colour)) || (i + 1 == stringLength)) { // The current character has a new font or new color or there is no next character RunAttribute attribute; attribute.range.setStart (rangeStart); attribute.range.setEnd (i); if (i + 1 == stringLength) attribute.range.setEnd (i+1); attribute.font = charAttributes[i-1].font; attribute.colour = charAttributes[i-1].colour; runAttributes.add (attribute); rangeStart = i; } } charAttributes.clear(); for (int i = 0; i < runAttributes.size(); ++i) { appendText (text, runAttributes[i].range, *(runAttributes[i].font), *(runAttributes[i].colour)); } runAttributes.clear(); // Run layout to break strings into words and create lines from words layout ((int) glyphLayout.getWidth()); // Use tokens to create Glyph Structures glyphLayout.setNumLines (getNumLines()); // Set Starting Positions to 0 int charPosition = 0; int lineStartPosition = 0; int runStartPosition = 0; // Create first GlyphLine and GlyphRun GlyphLine* glyphLine = new GlyphLine(); GlyphRun* glyphRun = new GlyphRun(); for (int i = 0; i < tokens.size(); ++i) { const Token* const t = tokens.getUnchecked (i); // See TextLayout::draw const float xOffset = (float) t->x; const float yOffset = (float) t->y; // See GlyphArrangement::addCurtailedLineOfText Array <int> newGlyphs; Array <float> xOffsets; t->font.getGlyphPositions (t->text.trimEnd(), newGlyphs, xOffsets); // Resize glyph run array glyphRun->setNumGlyphs (glyphRun->getNumGlyphs() + newGlyphs.size()); // Add each glyph in the token to the current GlyphRun for (int j = 0; j < newGlyphs.size(); ++j) { const float thisX = xOffsets.getUnchecked (j); // Check if this is the first character in the line if (charPosition == lineStartPosition) { // Save line offset data Point<float> origin (xOffset, yOffset + t->font.getAscent()); glyphLine->setLineOrigin (origin); } float xPos = glyphLayout.getX() + glyphLine->getLineOrigin().getX() + xOffset + thisX; float yPos = glyphLayout.getY() + glyphLine->getLineOrigin().getY(); Glyph* glyph = new Glyph (newGlyphs.getUnchecked(j), xPos, yPos); glyphRun->addGlyph (glyph); charPosition++; } if (t->isWhitespace || t->isNewLine) ++charPosition; // We have reached the end of a token, we may need to create a new run or line if (i + 1 == tokens.size()) { // We have reached the last token // Close GlyphRun Range<int> runRange (runStartPosition, charPosition); glyphRun->setStringRange (runRange); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); // Check if run descent is the largest in the line if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addGlyphRun (glyphRun); // Close GlyphLine Range<int> lineRange (lineStartPosition, charPosition); glyphLine->setStringRange (lineRange); glyphLayout.addGlyphLine (glyphLine); } else { // We have not yet reached the last token const Token* const nextt = tokens.getUnchecked (i+1); if (t->font != nextt->font || t->colour != nextt->colour) { //The next token has a new font or new colour // Close GlyphRun Range<int> runRange (runStartPosition, charPosition); glyphRun->setStringRange (runRange); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); // Check if run descent is the largest in the line if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addGlyphRun (glyphRun); // Create the next GlyphRun runStartPosition = charPosition; glyphRun = new GlyphRun(); } if (t->line != nextt->line) { // The next token is in a new line // Close GlyphRun Range<int> runRange (runStartPosition, charPosition); glyphRun->setStringRange (runRange); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); // Check if run descent is the largest in the line if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addGlyphRun (glyphRun); // Close GlyphLine Range<int> lineRange (lineStartPosition, charPosition); glyphLine->setStringRange (lineRange); glyphLayout.addGlyphLine (glyphLine); // Create the next GlyphLine and GlyphRun runStartPosition = charPosition; lineStartPosition = charPosition; glyphLine = new GlyphLine(); glyphRun = new GlyphRun(); } } } // Apply Layout Text Alignment if (text.getTextAlignment() == AttributedString::right || text.getTextAlignment() == AttributedString::center) { int totalW = (int) glyphLayout.getWidth(); for (int i = 0; i < getNumLines(); ++i) { const int lineW = getLineWidth (i); int dx = 0; if (text.getTextAlignment() == AttributedString::right) { dx = totalW - lineW; } else if (text.getTextAlignment() == AttributedString::center) { dx = (totalW - lineW) / 2; } GlyphLine& glyphLine = glyphLayout.getGlyphLine (i); Point<float> lineOrigin = glyphLine.getLineOrigin(); lineOrigin.setX (lineOrigin.getX() + dx); glyphLine.setLineOrigin (lineOrigin); } } }
void SplineControl::render(void) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(position.getX(), position.getY(), 0.0f); saveTransform(); glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT); glLineWidth(1.0f); if(dirty) { glNewList(displayList, GL_COMPILE); renderBackgroundMask(); glColor4f(1.0f, 1.0f, 1.0f, LINE_OPACITY); glBegin(GL_LINE_LOOP); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(width, 0.0f, 0.0f); glVertex3f(width, height, 0.0f); glVertex3f(0.0f, height, 0.0f); glEnd(); glColor4f(1.0f, 1.0f, 1.0f, 0.33f); // centre line glBegin(GL_LINE_STRIP); glVertex3f(0.0f, height / 2.0f, 0.0f); glVertex3f(width, height / 2.0f, 0.0f); glEnd(); float legendDim = height * LEGEND_DIM; // divisions for(unsigned int i = 0; i < InterfaceManager::BEATS; i++) { float pos = InterfaceManager::getBeatLength() * (float)i; if(pos > width) { break; } else { glBegin(GL_LINE_STRIP); glVertex3f(pos, legendDim, 0.0f); glVertex3f(pos, height - legendDim, 0.0f); glEnd(); } } // legends glColor4f(1.0f, 1.0f, 1.0f, LINE_OPACITY); glBegin(GL_LINES); glVertex3f(0.0f, legendDim, 0.0f); glVertex3f(width, legendDim, 0.0f); glVertex3f(0.0f, height - legendDim, 0.0f); glVertex3f(width, height - legendDim, 0.0f); glEnd(); float xIncrement = InterfaceManager::getBeatLength() / (float)LEGEND_BEAT_SUBDIVISIONS; for(unsigned int i = 0; xIncrement * (float)i < width; i++) { float lineLength = legendDim; if((i % LEGEND_BEAT_SUBDIVISIONS) != 0) { lineLength *= LEGEND_SUBBEAT_DIM; } glBegin(GL_LINES); // top glVertex3f(xIncrement * i, legendDim, 0.0f); glVertex3f(xIncrement * i, legendDim - lineLength, 0.0f); // bottom glVertex3f(xIncrement * i, height - legendDim, 0.0f); glVertex3f(xIncrement * i, (height - legendDim) + lineLength, 0.0f); glEnd(); } glEndList(); dirty = false; } glCallList(displayList); glLineWidth(getLineWidth(1.0f)); if(splineDirty) { glNewList(splineDisplayList, GL_COMPILE); renderSplineControl(width); glEndList(); splineDirty = false; } glCallList(splineDisplayList); renderInterfaceElements(); glPopAttrib(); glPopMatrix(); }
float LineLayer::Impl::getQueryRadius() const { const std::array<float, 2>& translate = paint.lineTranslate; return getLineWidth() / 2.0 + std::abs(paint.lineOffset) + util::length(translate[0], translate[1]); }
void createLayout (const AttributedString& text, TextLayout& layout) { tokens.ensureStorageAllocated (64); layout.ensureStorageAllocated (totalLines); addTextRuns (text); layoutRuns ((int) layout.getWidth()); int charPosition = 0; int lineStartPosition = 0; int runStartPosition = 0; TextLayout::Line* glyphLine = new TextLayout::Line(); TextLayout::Run* glyphRun = new TextLayout::Run(); for (int i = 0; i < tokens.size(); ++i) { const Token* const t = tokens.getUnchecked (i); const Point<float> tokenPos (t->area.getPosition().toFloat()); Array <int> newGlyphs; Array <float> xOffsets; t->font.getGlyphPositions (t->text.trimEnd(), newGlyphs, xOffsets); glyphRun->glyphs.ensureStorageAllocated (glyphRun->glyphs.size() + newGlyphs.size()); for (int j = 0; j < newGlyphs.size(); ++j) { if (charPosition == lineStartPosition) glyphLine->lineOrigin = tokenPos.translated (0, t->font.getAscent()); const float x = xOffsets.getUnchecked (j); glyphRun->glyphs.add (TextLayout::Glyph (newGlyphs.getUnchecked(j), Point<float> (tokenPos.getX() + x, 0), xOffsets.getUnchecked (j + 1) - x)); ++charPosition; } if (t->isWhitespace || t->isNewLine) ++charPosition; const Token* const nextToken = tokens [i + 1]; if (nextToken == nullptr) // this is the last token { addRun (glyphLine, glyphRun, t, runStartPosition, charPosition); glyphLine->stringRange = Range<int> (lineStartPosition, charPosition); layout.addLine (glyphLine); } else { if (t->font != nextToken->font || t->colour != nextToken->colour) { addRun (glyphLine, glyphRun, t, runStartPosition, charPosition); runStartPosition = charPosition; glyphRun = new TextLayout::Run(); } if (t->line != nextToken->line) { addRun (glyphLine, glyphRun, t, runStartPosition, charPosition); glyphLine->stringRange = Range<int> (lineStartPosition, charPosition); layout.addLine (glyphLine); runStartPosition = charPosition; lineStartPosition = charPosition; glyphLine = new TextLayout::Line(); glyphRun = new TextLayout::Run(); } } } if ((text.getJustification().getFlags() & (Justification::right | Justification::horizontallyCentred)) != 0) { const int totalW = (int) layout.getWidth(); for (int i = 0; i < totalLines; ++i) { const int lineW = getLineWidth (i); float dx = 0; if ((text.getJustification().getFlags() & Justification::right) != 0) dx = (float) (totalW - lineW); else dx = (totalW - lineW) / 2.0f; TextLayout::Line& glyphLine = layout.getLine (i); glyphLine.lineOrigin.x += dx; } } }
void MacText::splitString(Common::String &str) { const char *s = str.c_str(); Common::String tmp; bool prevCR = false; if (_textLines.empty()) { _textLines.resize(1); _textLines[0].chunks.push_back(_defaultFormatting); } int curLine = _textLines.size() - 1; int curChunk = _textLines[curLine].chunks.size() - 1; bool nextChunk = false; MacFontRun previousFormatting; while (*s) { #if DEBUG for (uint i = 0; i < _textLines.size(); i++) { debugN(7, "%2d ", i); for (uint j = 0; j < _textLines[i].chunks.size(); j++) debugN(7, "[%d] \"%s\"", _textLines[i].chunks[j].fontId, _textLines[i].chunks[j].text.c_str()); debug(7, " --> %c %d, '%s'", (*s > 0x20 ? *s : ' '), (byte)*s, tmp.c_str()); } #endif if (*s == '\001') { s++; if (*s == '\001') { // Copy it verbatim } else { if (*s++ != '\015') error("MacText: formatting error"); uint16 fontId = *s++; fontId = (fontId << 8) | *s++; byte textSlant = *s++; byte unk3f = *s++; uint16 fontSize = *s++; fontSize = (fontSize << 8) | *s++; uint16 palinfo1 = *s++; palinfo1 = (palinfo1 << 8) | *s++; uint16 palinfo2 = *s++; palinfo2 = (palinfo2 << 8) | *s++; uint16 palinfo3 = *s++; palinfo3 = (palinfo3 << 8) | *s++; debug(8, "******** splitString: fontId: %d, textSlant: %d, unk3: %d, fontSize: %d, p0: %x p1: %x p2: %x", fontId, textSlant, unk3f, fontSize, palinfo1, palinfo2, palinfo3); previousFormatting = _currentFormatting; _currentFormatting.setValues(_wm, fontId, textSlant, unk3f, fontSize, palinfo1, palinfo2, palinfo3); if (curLine == 0 && curChunk == 0 && tmp.empty()) previousFormatting = _currentFormatting; nextChunk = true; } } else if (*s == '\n' && prevCR) { // trean \r\n as one prevCR = false; s++; continue; } else if (*s == '\r') { prevCR = true; } if (*s == '\r' || *s == '\n' || nextChunk) { Common::Array<Common::String> text; if (!nextChunk) previousFormatting = _currentFormatting; int w = getLineWidth(curLine, true); previousFormatting.getFont()->wordWrapText(tmp, _maxWidth, text, w); tmp.clear(); if (text.size()) { for (uint i = 0; i < text.size(); i++) { _textLines[curLine].chunks[curChunk].text = text[i]; if ((text.size() > 1 || !nextChunk) && !(i == text.size() - 1 && nextChunk)) { curLine++; _textLines.resize(curLine + 1); _textLines[curLine].chunks.push_back(previousFormatting); curChunk = 0; } } if (nextChunk) { curChunk++; _textLines[curLine].chunks.push_back(_currentFormatting); } else { _textLines[curLine].chunks[0] = _currentFormatting; } } else { if (nextChunk) { // No text, replacing formatting _textLines[curLine].chunks[curChunk] = _currentFormatting; } else { // Otherwise it is an empty line curLine++; _textLines.resize(curLine + 1); _textLines[curLine].chunks.push_back(previousFormatting); curChunk = 0; } } if (!nextChunk) // Don't skip next character s++; nextChunk = false; continue; } tmp += *s; s++; } if (tmp.size()) { Common::Array<Common::String> text; int w = getLineWidth(curLine, true); _currentFormatting.getFont()->wordWrapText(tmp, _maxWidth, text, w); _textLines[curLine].chunks[curChunk].text = text[0]; if (text.size() > 1) { for (uint i = 1; i < text.size(); i++) { curLine++; _textLines.resize(curLine + 1); _textLines[curLine].chunks.push_back(_currentFormatting); _textLines[curLine].chunks[0].text = text[i]; } } } }
void createLayout (const AttributedString& text, GlyphLayout& glyphLayout) { tokens.ensureStorageAllocated (64); glyphLayout.ensureStorageAllocated (totalLines); addTextRuns (text); layout ((int) glyphLayout.area.getWidth()); int charPosition = 0; int lineStartPosition = 0; int runStartPosition = 0; GlyphLayout::Line* glyphLine = new GlyphLayout::Line(); GlyphLayout::Run* glyphRun = new GlyphLayout::Run(); for (int i = 0; i < tokens.size(); ++i) { const Token* const t = tokens.getUnchecked (i); const Point<float> tokenPos (t->area.getPosition().toFloat()); Array <int> newGlyphs; Array <float> xOffsets; t->font.getGlyphPositions (t->text.trimEnd(), newGlyphs, xOffsets); glyphRun->ensureStorageAllocated (glyphRun->getNumGlyphs() + newGlyphs.size()); for (int j = 0; j < newGlyphs.size(); ++j) { if (charPosition == lineStartPosition) glyphLine->setLineOrigin (tokenPos.translated (0, t->font.getAscent())); glyphRun->addGlyph (new GlyphLayout::Glyph (newGlyphs.getUnchecked(j), (glyphLayout.area.getPosition() + glyphLine->getLineOrigin()) .translated (tokenPos.getX() + xOffsets.getUnchecked (j), 0))); ++charPosition; } if (t->isWhitespace || t->isNewLine) ++charPosition; const Token* const nextToken = tokens [i + 1]; if (nextToken == nullptr) // this is the last token { glyphRun->setStringRange (Range<int> (runStartPosition, charPosition)); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addRun (glyphRun); glyphLine->setStringRange (Range<int> (lineStartPosition, charPosition)); glyphLayout.addLine (glyphLine); } else { if (t->font != nextToken->font || t->colour != nextToken->colour) { glyphRun->setStringRange (Range<int> (runStartPosition, charPosition)); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addRun (glyphRun); runStartPosition = charPosition; glyphRun = new GlyphLayout::Run(); } if (t->line != nextToken->line) { glyphRun->setStringRange (Range<int> (runStartPosition, charPosition)); glyphRun->setFont (t->font); glyphRun->setColour (t->colour); if (t->font.getDescent() > glyphLine->getDescent()) glyphLine->setDescent (t->font.getDescent()); glyphLine->addRun (glyphRun); glyphLine->setStringRange (Range<int> (lineStartPosition, charPosition)); glyphLayout.addLine (glyphLine); runStartPosition = charPosition; lineStartPosition = charPosition; glyphLine = new GlyphLayout::Line(); glyphRun = new GlyphLayout::Run(); } } } if (text.getTextAlignment() == AttributedString::right || text.getTextAlignment() == AttributedString::center) { const int totalW = (int) glyphLayout.area.getWidth(); for (int i = 0; i < totalLines; ++i) { const int lineW = getLineWidth (i); float dx = 0; if (text.getTextAlignment() == AttributedString::right) dx = (float) (totalW - lineW); else if (text.getTextAlignment() == AttributedString::center) dx = (totalW - lineW) / 2.0f; GlyphLayout::Line& glyphLine = glyphLayout.getLine (i); glyphLine.setLineOrigin (glyphLine.getLineOrigin().translated (dx, 0)); } } }
void SWFontRenderer::updateMesh() { if ( !getMesh() ) return; if ( !m_fontInfo.isValid() ) return; SWMesh* mesh = getMesh(); mesh->resizeVertexStream( m_text.size() * 4 ); mesh->resizeTexCoordStream( m_text.size() * 4 ); mesh->resizeTriangleStream( m_text.size() * 2 ); tuint32 lastID = '\r'; tvec2 cursor( 0, 0 ); tvec2 scale( m_fontInfo()->getScaleW(), m_fontInfo()->getScaleH() ); float lineHeight = getLinesHeight( m_text ); switch ( m_alignV ) { case SW_Align_Top : cursor.y = 0; break; case SW_Align_Bottom : cursor.y = lineHeight; break; case SW_Align_Center : cursor.y = lineHeight/2.0f; break; } for ( tuint i = 0 ; i < m_text.size() ; ++i ) { //! convert character to unsigned char id tbyte byteID = m_text[i]; tuint32 id = byteID; if ( lastID == (int)'\n' || lastID == (int)'\r' ) { float lineWidth = (float)getLineWidth( m_text, i ); switch ( m_alignH ) { case SW_Align_Left : cursor.x = 0; break; case SW_Align_Right : cursor.x = -lineWidth; break; case SW_Align_Center : cursor.x = -lineWidth/2.0f; break; } } if ( id == (int)'\n' || id == (int)'\r' ) { lastID = id; cursor.y -= m_fontInfo()->getLineHeight(); continue; } SWFontInfo::Char* fontChar = m_fontInfo()->getChar( id ); if ( fontChar == NULL ) continue; SWFontInfo::Kerning* kerning = m_fontInfo()->getKerning( lastID, id ); cursor.x += (kerning != NULL)? kerning->amount : 0; lastID = id; tuint base = i*4; float left = cursor.x + fontChar->xoffset; float top = cursor.y - fontChar->yoffset; float right = left + fontChar->width; float bottom = top - fontChar->height; cursor.x += fontChar->xadvence; mesh->setTriangle( (i*2)+0, tindex3( base+0, base+1, base+2 ) ); mesh->setTriangle( (i*2)+1, tindex3( base+3, base+2, base+1 ) ); mesh->setVertex( base+0, tvec3( left, top, 0 ) ); mesh->setVertex( base+1, tvec3( right, top, 0 ) ); mesh->setVertex( base+2, tvec3( left, bottom, 0 ) ); mesh->setVertex( base+3, tvec3( right, bottom, 0 ) ); mesh->setTexCoord( base+0, tvec2( fontChar->x/scale.x, fontChar->y/scale.y ) ); mesh->setTexCoord( base+1, tvec2( (fontChar->x + fontChar->width)/scale.x, fontChar->y/scale.y ) ); mesh->setTexCoord( base+2, tvec2( fontChar->x/scale.x, (fontChar->y + fontChar->height)/scale.y ) ); mesh->setTexCoord( base+3, tvec2( (fontChar->x + fontChar->width)/scale.x, (fontChar->y + fontChar->height)/scale.y ) ); } }
void LineLayer::setLineWidth(PropertyValue<float> value, const optional<std::string>& klass) { if (value == getLineWidth(klass)) return; impl->paint.lineWidth.set(value, klass); impl->observer->onLayerPaintPropertyChanged(*this); }
uint FontHelper::getTextWidth(vector<string> *text) { int w = 0; for (uint i=0; i<text->size(); i++) w = max( getLineWidth(text->at(i)), w ); return w; }