FontStyle* FontStyleManager::requestFontStyle(string style){ list <FontStyle*>::iterator it; for (it = mFontStyle.begin();it != mFontStyle.end();it++){ if ((*it)->getName() == style){ return (*it); } } /*File f(style+".xml", "media\\fonts"); if (f.error() != FILE_OK){ throw ("Font Style Not Found : "+style); } XML* xml = new XML(f.getStrContent());*/ XML* xml = new XML(style+".xml", "media\\fonts"); XMLIterator xIt(xml); xIt.setElemName("fontstyle"); xIt.gotoZero(); xIt.gotoNext(); FontStyle* fs = new FontStyle(style, xIt.getElem().getString("font"), xIt.getElem().getFloat("size")); Ogre::ColourValue prim = colourValueFromString(xIt.getElem().getString("colour")); Ogre::ColourValue sec = colourValueFromString(xIt.getElem().getString("shadow")); fs->setColour(prim, sec); delete xml; mFontStyle.push_back(fs); return fs; }
/*! \brief This saves all family names and styles to the file specified in ServerConfig.h as SERVER_FONT_LIST as a flattened BMessage. This operation is not done very often because the access to disk adds a significant performance hit. The format for storage consists of two things: an array of strings with the name 'family' and a number of small string arrays which have the name of the font family. These are the style lists. Additionally, any fonts which have bitmap strikes contained in them or any fonts which are fixed-width are named in the arrays 'tuned' and 'fixed'. */ void FontServer::SaveList(void) { int32 famcount=0, stycount=0,i=0,j=0; FontFamily *fam; FontStyle *sty; BMessage fontmsg, familymsg('FONT'); BString famname, styname, extraname; bool fixed,tuned; famcount=families->CountItems(); for(i=0; i<famcount; i++) { fam=(FontFamily*)families->ItemAt(i); fixed=false; tuned=false; if(!fam) continue; famname=fam->Name(); // Add the family to the message familymsg.AddString("name",famname); stycount=fam->CountStyles(); for(j=0;j<stycount;j++) { styname.SetTo(fam->GetStyle(j)); if(styname.CountChars()>0) { // Add to list familymsg.AddString("styles", styname); // Check to see if it has prerendered strikes (has "tuned" fonts) sty=fam->GetStyle(styname.String()); if(!sty) continue; if(sty->HasTuned() && sty->IsScalable()) tuned=true; // Check to see if it is fixed-width if(sty->IsFixedWidth()) fixed=true; } } if(tuned) familymsg.AddBool("tuned",true); if(fixed) familymsg.AddBool("fixed",true); fontmsg.AddMessage("family",&familymsg); familymsg.MakeEmpty(); } BFile file(SERVER_FONT_LIST,B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); if(file.InitCheck()==B_OK) fontmsg.Flatten(&file); }
// Compute a matching metric between two styles - 0 is an exact match static int computeMatch(FontStyle style1, FontStyle style2) { if (style1 == style2) return 0; int score = abs(style1.getWeight() - style2.getWeight()); if (style1.getItalic() != style2.getItalic()) { score += 2; } return score; }
FontFamily* FontManager::GetFamily(uint16 familyID) const { FontKey key(familyID, 0); FontStyle* style = (FontStyle*)fStyleHashTable.GetValue(key); if (style != NULL) return style->Family(); return NULL; }
static FontFakery computeFakery(FontStyle wanted, FontStyle actual) { // If desired weight is semibold or darker, and 2 or more grades // higher than actual (for example, medium 500 -> bold 700), then // select fake bold. int wantedWeight = wanted.getWeight(); bool isFakeBold = wantedWeight >= 6 && (wantedWeight - actual.getWeight()) >= 2; bool isFakeItalic = wanted.getItalic() && !actual.getItalic(); return FontFakery(isFakeBold, isFakeItalic); }
/*! \brief Destructor Deletes all attached styles. Note that a FontFamily must only be deleted by the font manager. */ FontFamily::~FontFamily() { for (int32 i = fStyles.CountItems(); i-- > 0;) { FontStyle* style = fStyles.RemoveItemAt(i); // we remove us before deleting the style, so that the font manager // is not contacted to remove the style from us style->_SetFontFamily(NULL, -1); delete style; } }
FontStyle* FontFamily::GetStyleByID(uint16 id) const { int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) { FontStyle* style = fStyles.ItemAt(i); if (style->ID() == id) return style; } return NULL; }
FontStyle* FontManager::font_directory::FindStyle(const node_ref& nodeRef) const { for (int32 i = styles.CountItems(); i-- > 0;) { FontStyle* style = styles.ItemAt(i); if (nodeRef == style->NodeRef()) return style; } return NULL; }
FontStyle* FontFamily::_FindStyle(const char* name) const { int32 count = fStyles.CountItems(); if (!name || count < 1) return NULL; for (int32 i = 0; i < count; i++) { FontStyle *style = fStyles.ItemAt(i); if (!strcmp(style->Name(), name)) return style; } return NULL; }
FontStyle* FontFamily::GetStyleMatchingFace(uint16 face) const { // TODO: support other faces (strike through, underlined, outlines...) face &= B_BOLD_FACE | B_ITALIC_FACE | B_REGULAR_FACE | B_CONDENSED_FACE | B_LIGHT_FACE | B_HEAVY_FACE; int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) { FontStyle* style = fStyles.ItemAt(i); if (style->Face() == face) return style; } return NULL; }
/*! \brief Constructor \param style Style object to which the ServerFont belongs \param size Character size in points \param rotation Rotation in degrees \param shear Shear (slant) in degrees. 45 <= shear <= 135 \param flags Style flags as defined in <Font.h> \param spacing String spacing flag as defined in <Font.h> */ ServerFont::ServerFont(FontStyle& style, float size, float rotation, float shear, float falseBoldWidth, uint16 flags, uint8 spacing) : fStyle(&style), fSize(size), fRotation(rotation), fShear(shear), fFalseBoldWidth(falseBoldWidth), fBounds(0, 0, 0, 0), fFlags(flags), fSpacing(spacing), fDirection(style.Direction()), fFace(style.Face()), fEncoding(B_UNICODE_UTF8) { fStyle->Acquire(); }
Rect glArchivItem_Font::getBounds(DrawPoint pos, const std::string& text, FontStyle format) const { if(text.empty()) return Rect(Position(pos), 0, 0); unsigned width = getWidth(text); unsigned numLines = static_cast<unsigned>(std::count(text.begin(), text.end(), '\n')) + 1; Rect result(Position(pos), width, numLines * getHeight()); Position offset(0, 0); if(format.is(FontStyle::RIGHT)) offset.x = width; else if(format.is(FontStyle::CENTER)) offset.x = width / 2; if(format.is(FontStyle::BOTTOM)) offset.y = getHeight(); else if(format.is(FontStyle::VCENTER)) offset.y = getHeight() / 2; result.move(-offset); return result; }
/*! \brief Sets the ServerFont instance to whatever font is specified This method will lock the font manager. \param familyID ID number of the family to set \param styleID ID number of the style to set \return B_OK if successful, B_ERROR if not */ status_t ServerFont::SetFamilyAndStyle(uint16 familyID, uint16 styleID) { FontStyle* style = NULL; if (gFontManager->Lock()) { style = gFontManager->GetStyle(familyID, styleID); if (style != NULL) style->Acquire(); gFontManager->Unlock(); } if (style == NULL) return B_ERROR; SetStyle(style); style->Release(); return B_OK; }
uint32 FontFamily::Flags() { if (fFlags == kInvalidFamilyFlags) { fFlags = 0; int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) { FontStyle* style = fStyles.ItemAt(i); if (style->IsFixedWidth()) fFlags |= B_IS_FIXED; if (style->IsFullAndHalfFixed()) fFlags |= B_PRIVATE_FONT_IS_FULL_AND_HALF_FIXED; if (style->TunedCount() > 0) fFlags |= B_HAS_TUNED_FONT; } } return fFlags; }
void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags, TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count, size_t bufSize) { TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface); layout->setFontCollection(resolvedFace->fFontCollection); FontStyle resolved = resolvedFace->fStyle; /* Prepare minikin FontStyle */ std::string lang = paint->getTextLocale(); FontLanguage minikinLang(lang.c_str(), lang.size()); FontVariant minikinVariant = (paint->getFontVariant() == VARIANT_ELEGANT) ? VARIANT_ELEGANT : VARIANT_COMPACT; FontStyle minikinStyle(minikinLang, minikinVariant, resolved.getWeight(), resolved.getItalic()); /* Prepare minikin Paint */ MinikinPaint minikinPaint; minikinPaint.size = (int)/*WHY?!*/paint->getTextSize(); minikinPaint.scaleX = paint->getTextScaleX(); minikinPaint.skewX = paint->getTextSkewX(); minikinPaint.letterSpacing = paint->getLetterSpacing(); minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint); minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings(); layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint); }
status_t ServerFont::SetFace(uint16 face) { // TODO: This needs further investigation. The face variable is actually // flags, but some of them are not enforcable at the same time. Also don't // confuse the Be API "face" with the Freetype face, which is just an // index in case a single font file exports multiple font faces. The // FontStyle class takes care of mapping the font style name to the Be // API face flags in FontStyle::_TranslateStyleToFace(). FontStyle* style = NULL; uint16 familyID = FamilyID(); if (gFontManager->Lock()) { int32 count = gFontManager->CountStyles(familyID); for (int32 i = 0; i < count; i++) { style = gFontManager->GetStyleByIndex(familyID, i); if (style == NULL) break; if (style->Face() == face) { style->Acquire(); break; } else style = NULL; } gFontManager->Unlock(); } if (!style) return B_ERROR; SetStyle(style); style->Release(); return B_OK; }
/*! \brief Adds the style to the family \param style pointer to FontStyle object to be added */ bool FontFamily::AddStyle(FontStyle *style) { if (!style) return false; // Don't add if it already is in the family. int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) { FontStyle *item = fStyles.ItemAt(i); if (!strcmp(item->Name(), style->Name())) return false; } if (!fStyles.BinaryInsert(style, compare_font_styles)) return false; style->_SetFontFamily(this, fNextID++); // force a refresh if a request for font flags is needed fFlags = kInvalidFamilyFlags; return true; }
void FontStyle::applyBaseStyle(const FontStyle& baseStyle, const ArgList& args) { setDefaultedAttr(m_sName, "font", args, baseStyle.getFont()); setDefaultedAttr(m_sVariant, "variant", args, baseStyle.getFontVariant()); setDefaultedAttr(m_Color, "color", args, baseStyle.getColor()); setDefaultedAttr(m_AAGamma, "aagamma", args, baseStyle.getAAGamma()); setDefaultedAttr(m_Size, "fontsize", args, baseStyle.getFontSize()); setDefaultedAttr(m_Indent, "indent", args, baseStyle.getIndent()); setDefaultedAttr(m_LineSpacing, "linespacing", args, baseStyle.getLineSpacing()); setDefaultedAttr(m_Alignment, "alignment", args, baseStyle.getAlignmentVal()); setDefaultedAttr(m_WrapMode, "wrapmode", args, baseStyle.getWrapModeVal()); setDefaultedAttr(m_bJustify, "justify", args, baseStyle.getJustify()); setDefaultedAttr(m_LetterSpacing, "letterspacing", args, baseStyle.getLetterSpacing()); setDefaultedAttr(m_bHint, "hint", args, baseStyle.getHint()); }
void FontManager::MessageReceived(BMessage* message) { switch (message->what) { case B_NODE_MONITOR: { // TODO: support removing fonts! int32 opcode; if (message->FindInt32("opcode", &opcode) != B_OK) return; switch (opcode) { case B_ENTRY_CREATED: { const char* name; node_ref nodeRef; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("directory", &nodeRef.node) != B_OK || message->FindString("name", &name) != B_OK) break; // TODO: make this better (possible under Haiku) snooze(100000); // let the font be written completely before trying to open it BEntry entry; if (set_entry(nodeRef, name, entry) != B_OK) break; if (entry.IsDirectory()) { // a new directory to watch for us _AddPath(entry); } else { // a new font font_directory* directory = _FindDirectory(nodeRef); if (directory == NULL) { // unknown directory? how come? break; } _AddFont(*directory, entry); } break; } case B_ENTRY_MOVED: { // has the entry been moved into a monitored directory or has // it been removed from one? const char* name; node_ref nodeRef; uint64 fromNode; uint64 node; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("to directory", &nodeRef.node) != B_OK || message->FindInt64("from directory", (int64 *)&fromNode) != B_OK || message->FindInt64("node", (int64 *)&node) != B_OK || message->FindString("name", &name) != B_OK) break; font_directory* directory = _FindDirectory(nodeRef); BEntry entry; if (set_entry(nodeRef, name, entry) != B_OK) break; if (directory != NULL) { // something has been added to our watched font directories // test, if the source directory is one of ours as well nodeRef.node = fromNode; font_directory* fromDirectory = _FindDirectory(nodeRef); if (entry.IsDirectory()) { if (fromDirectory == NULL) { // there is a new directory to watch for us _AddPath(entry); FTRACE("new directory moved in"); } else { // A directory from our watched directories has // been renamed or moved within the watched // directories - we only need to update the // path names of the styles in that directory nodeRef.node = node; directory = _FindDirectory(nodeRef); if (directory != NULL) { for (int32 i = 0; i < directory->styles.CountItems(); i++) { FontStyle* style = directory->styles.ItemAt(i); style->UpdatePath(directory->directory); } } FTRACE("directory renamed"); } } else { if (fromDirectory != NULL) { // find style in source and move it to the target nodeRef.node = node; FontStyle* style = fromDirectory->FindStyle(nodeRef); if (style != NULL) { fromDirectory->styles.RemoveItem(style, false); directory->styles.AddItem(style); style->UpdatePath(directory->directory); } FTRACE(("font moved")); } else { FTRACE(("font added: %s\n", name)); _AddFont(*directory, entry); } } } else { // and entry has been removed from our font directories if (entry.IsDirectory()) { if (entry.GetNodeRef(&nodeRef) == B_OK && (directory = _FindDirectory(nodeRef)) != NULL) _RemoveDirectory(directory); } else { // remove font style from directory _RemoveStyle(nodeRef.device, fromNode, node); } } break; } case B_ENTRY_REMOVED: { node_ref nodeRef; uint64 directoryNode; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("directory", (int64 *)&directoryNode) != B_OK || message->FindInt64("node", &nodeRef.node) != B_OK) break; font_directory* directory = _FindDirectory(nodeRef); if (directory != NULL) { // the directory has been removed, so we remove it as well _RemoveDirectory(directory); } else { // remove font style from directory _RemoveStyle(nodeRef.device, directoryNode, nodeRef.node); } break; } } break; } } }
status_t DesktopSettingsPrivate::_Load() { // TODO: add support for old app_server_settings file as well BPath basePath; status_t status = _GetPath(basePath); if (status < B_OK) return status; // read workspaces settings BPath path(basePath); path.Append("workspaces"); BFile file; status = file.SetTo(path.Path(), B_READ_ONLY); if (status == B_OK) { BMessage settings; status = settings.Unflatten(&file); if (status == B_OK) { int32 columns; int32 rows; if (settings.FindInt32("columns", &columns) == B_OK && settings.FindInt32("rows", &rows) == B_OK) { _ValidateWorkspacesLayout(columns, rows); fWorkspacesColumns = columns; fWorkspacesRows = rows; } int32 i = 0; while (i < kMaxWorkspaces && settings.FindMessage("workspace", i, &fWorkspaceMessages[i]) == B_OK) { i++; } } } // read font settings path = basePath; path.Append("fonts"); status = file.SetTo(path.Path(), B_READ_ONLY); if (status == B_OK) { BMessage settings; status = settings.Unflatten(&file); if (status == B_OK && gFontManager->Lock()) { const char* family; const char* style; float size; if (settings.FindString("plain family", &family) == B_OK && settings.FindString("plain style", &style) == B_OK && settings.FindFloat("plain size", &size) == B_OK) { FontStyle* fontStyle = gFontManager->GetStyle(family, style); fPlainFont.SetStyle(fontStyle); fPlainFont.SetSize(size); } if (settings.FindString("bold family", &family) == B_OK && settings.FindString("bold style", &style) == B_OK && settings.FindFloat("bold size", &size) == B_OK) { FontStyle* fontStyle = gFontManager->GetStyle(family, style); fBoldFont.SetStyle(fontStyle); fBoldFont.SetSize(size); } if (settings.FindString("fixed family", &family) == B_OK && settings.FindString("fixed style", &style) == B_OK && settings.FindFloat("fixed size", &size) == B_OK) { FontStyle* fontStyle = gFontManager->GetStyle(family, style); if (fontStyle != NULL && fontStyle->IsFixedWidth()) fFixedFont.SetStyle(fontStyle); fFixedFont.SetSize(size); } int32 hinting; if (settings.FindInt32("hinting", &hinting) == B_OK) gDefaultHintingMode = hinting; gFontManager->Unlock(); } } // read mouse settings path = basePath; path.Append("mouse"); status = file.SetTo(path.Path(), B_READ_ONLY); if (status == B_OK) { BMessage settings; status = settings.Unflatten(&file); if (status == B_OK) { int32 mode; if (settings.FindInt32("mode", &mode) == B_OK) fMouseMode = (mode_mouse)mode; int32 focusFollowsMouseMode; if (settings.FindInt32("focus follows mouse mode", &focusFollowsMouseMode) == B_OK) { fFocusFollowsMouseMode = (mode_focus_follows_mouse)focusFollowsMouseMode; } bool acceptFirstClick; if (settings.FindBool("accept first click", &acceptFirstClick) == B_OK) { fAcceptFirstClick = acceptFirstClick; } } } // read appearance settings path = basePath; path.Append("appearance"); status = file.SetTo(path.Path(), B_READ_ONLY); if (status == B_OK) { BMessage settings; status = settings.Unflatten(&file); if (status == B_OK) { // menus float fontSize; if (settings.FindFloat("font size", &fontSize) == B_OK) fMenuInfo.font_size = fontSize; const char* fontFamily; if (settings.FindString("font family", &fontFamily) == B_OK) strlcpy(fMenuInfo.f_family, fontFamily, B_FONT_FAMILY_LENGTH); const char* fontStyle; if (settings.FindString("font style", &fontStyle) == B_OK) strlcpy(fMenuInfo.f_style, fontStyle, B_FONT_STYLE_LENGTH); rgb_color bgColor; if (settings.FindInt32("bg color", (int32*)&bgColor) == B_OK) fMenuInfo.background_color = bgColor; int32 separator; if (settings.FindInt32("separator", &separator) == B_OK) fMenuInfo.separator = separator; bool clickToOpen; if (settings.FindBool("click to open", &clickToOpen) == B_OK) fMenuInfo.click_to_open = clickToOpen; bool triggersAlwaysShown; if (settings.FindBool("triggers always shown", &triggersAlwaysShown) == B_OK) { fMenuInfo.triggers_always_shown = triggersAlwaysShown; } // scrollbars bool proportional; if (settings.FindBool("proportional", &proportional) == B_OK) fScrollBarInfo.proportional = proportional; bool doubleArrows; if (settings.FindBool("double arrows", &doubleArrows) == B_OK) fScrollBarInfo.double_arrows = doubleArrows; int32 knob; if (settings.FindInt32("knob", &knob) == B_OK) fScrollBarInfo.knob = knob; int32 minKnobSize; if (settings.FindInt32("min knob size", &minKnobSize) == B_OK) fScrollBarInfo.min_knob_size = minKnobSize; // subpixel font rendering bool subpix; if (settings.FindBool("subpixel antialiasing", &subpix) == B_OK) gSubpixelAntialiasing = subpix; int8 averageWeight; if (settings.FindInt8("subpixel average weight", &averageWeight) == B_OK) { gSubpixelAverageWeight = averageWeight; } bool subpixelOrdering; if (settings.FindBool("subpixel ordering", &subpixelOrdering) == B_OK) { gSubpixelOrderingRGB = subpixelOrdering; } // colors for (int32 i = 0; i < kNumColors; i++) { char colorName[12]; snprintf(colorName, sizeof(colorName), "color%" B_PRId32, (int32)index_to_color_which(i)); settings.FindInt32(colorName, (int32*)&fShared.colors[i]); } } } // read dragger settings path = basePath; path.Append("dragger"); status = file.SetTo(path.Path(), B_READ_ONLY); if (status == B_OK) { BMessage settings; status = settings.Unflatten(&file); if (status == B_OK) { if (settings.FindBool("show", &fShowAllDraggers) != B_OK) fShowAllDraggers = true; } } return B_OK; }
// Initialize GLUT & OpenSG and set up the scene int main(int argc, char **argv) { cout << "Testing screen aligned text generation and file-IO." << endl; if(argc == 1) { FFATAL(("Need *.txf or *.ttf font file\n")); return -1; } // OSG init osgInit(argc, argv); // GLUT init int winid = setupGLUT(&argc, argv); // the connection between GLUT and OpenSG GLUTWindowPtr gwin = GLUTWindow::create(); gwin->setId(winid); gwin->init(); PathHandler paths; paths.push_backPath("."); //paths.push_backPath("/home/elmi/wrk/development/texFont"); // create the scene FontStyle *fontStyle = FontStyleFactory::the().create( paths, argv[1], 0.25); cout << fontStyle->getFontName() << endl; // create the scene NodePtr pTorus = makeTorus( 0.02, 0.55, 16, 16); ChunkMaterialPtr mat = ChunkMaterial::create(); MaterialChunkPtr pmc = MaterialChunk::create(); pmc->setDiffuse( Color4f( 1,0,0,0.5 ) ); pmc->setAmbient( Color4f( 0,1,0,0.5 ) ); pmc->setSpecular( Color4f( 0,0,1,0.5 ) ); pmc->setLit( true ); pmc->setShininess( 20 ); beginEditCP(mat); { mat->addChunk( pmc ); } endEditCP(mat); scene = Node::create(); GroupPtr group = Group::create(); beginEditCP( scene ); { scene->setCore( group ); } endEditCP( scene ); SharedFontStylePtr sfs = SharedFontStyle::create(); sfs->setContainedFontStyle( fontStyle ); for( int x=0; x<100; x += 20 ) { for( int y=0; y<100; y += 20 ) { for( int z=0; z<100; z += 20 ) { ScreenAlignedTextPtr scaText = ScreenAlignedText::create(); if( scaText == NullFC ) { exit (2); } SharedFontStyleWrapperPtr pFSWrapper = SharedFontStyleWrapper::create(); pFSWrapper->setFStyleContainer( sfs ); ostringstream cString; cString << '(' << x << ',' << y << ',' << z << ')' << endl; beginEditCP(scaText); { scaText->setPosition( Vec3f ( x, y, z ) ); scaText->setFont( pFSWrapper ); scaText->setVerticalLineDistance( 0.20 ); scaText->setAlignment( 0 ); scaText->editMFText()->push_back( cString.str() ); scaText->setMaterial( mat ); } endEditCP(scaText); NodePtr pTextNode = Node::create(); beginEditCP( pTextNode ); { pTextNode->setCore( scaText ); } beginEditCP( scene ); { scene->addChild( pTextNode ); } endEditCP( scene ); cout << "Erzeugt : " << cString.str() << endl; } } } //NodePtr pCopied = scene; #if 1 { ofstream outFileStream( "/tmp/text.osg" ); if( !outFileStream ) { cerr << "cannot open file" << endl; exit(2); } //FILE *pFile = fopen( "isolinien.osg","w" ); //BINWriter writer( pFile ); OSGWriter writer( outFileStream ); writer.write( scene ); } #endif #if 0 VRMLWriteAction *pWriter = VRMLWriteAction::create(); scene->dump(); pWriter->open("allesscheisse.wrl"); pWriter->write( scene); pWriter->close(); delete pWriter; #endif // create the SimpleSceneManager helper mgr = new SimpleSceneManager; // tell the manager what to manage mgr->setWindow(gwin); mgr->setRoot( scene ); // show the whole scene mgr->showAll(); // GLUT main loop glutMainLoop(); return 0; }
/** * Zeichnet einen Text. * * @param[in] x X-Koordinate * @param[in] y Y-Koordinate * @param[in] text Der Text * @param[in] format Format des Textes (verodern) * @p FontStyle::LEFT - Text links ( standard ) * @p FontStyle::CENTER - Text mittig * @p FontStyle::RIGHT - Text rechts * @p FontStyle::TOP - Text oben ( standard ) * @p FontStyle::VCENTER - Text vertikal zentriert * @p FontStyle::BOTTOM - Text unten * @param[in] color Farbe des Textes * @param[in] length Länge des Textes * @param[in] max maximale Länge * @param end Suffix for displaying a truncation of the text (...) */ void glArchivItem_Font::Draw(DrawPoint pos, const std::string& text, FontStyle format, unsigned color, unsigned short length, unsigned short maxWidth, const std::string& end) { if(!fontNoOutline) initFont(); RTTR_Assert(isValidUTF8(text)); // Breite bestimmen if(length == 0) length = (unsigned short)text.length(); unsigned maxNumChars; unsigned short textWidth; bool drawEnd; if(maxWidth == 0xFFFF) { maxNumChars = length; textWidth = getWidth(text, length); drawEnd = false; } else { RTTR_Assert(isValidUTF8(end)); textWidth = getWidth(text, length, maxWidth, &maxNumChars); if(!end.empty() && maxNumChars < length) { unsigned short endWidth = getWidth(end); // If "end" does not fit, draw nothing if(textWidth < endWidth) return; // Wieviele Buchstaben gehen in den "Rest" (ohne "end") textWidth = getWidth(text, length, textWidth - endWidth, &maxNumChars) + endWidth; drawEnd = true; } else drawEnd = false; } if(maxNumChars == 0) return; auto itEnd = text.cbegin(); std::advance(itEnd, maxNumChars); // Vertical alignment (assumes 1 line only!) if(format.is(FontStyle::BOTTOM)) pos.y -= dy; else if(format.is(FontStyle::VCENTER)) pos.y -= dy / 2; // Horizontal center must change current line only. Everything else changes the start point DrawPoint curPos(pos); // Horizontal alignment if(format.is(FontStyle::RIGHT)) curPos.x = pos.x -= textWidth; else if(format.is(FontStyle::CENTER)) { unsigned short line_width; const auto itNl = std::find(text.cbegin(), itEnd, '\n'); if(itNl != itEnd) line_width = getWidthInternal(text.cbegin(), itNl); else line_width = textWidth; curPos.x = pos.x - line_width / 2; } texList.texCoords.clear(); texList.vertices.clear(); for(auto it = text.begin(); it != itEnd;) { const uint32_t curChar = utf8::next(it, itEnd); if(curChar == '\n') { if(format.is(FontStyle::CENTER)) { unsigned short line_width; const auto itNl = std::find(it, itEnd, '\n'); line_width = getWidthInternal(it, itNl); curPos.x = pos.x - line_width / 2; } else curPos.x = pos.x; curPos.y += dy; } else DrawChar(curChar, texList, curPos); } if(drawEnd) { for(auto it = end.begin(); it != end.end();) { const uint32_t curChar = utf8::next(it, end.end()); if(curChar == '\n') { curPos.x = pos.x; curPos.y += dy; } else DrawChar(curChar, texList, curPos); } } if(texList.vertices.empty()) return; // Get texture first as it might need to be created glArchivItem_Bitmap& usedFont = format.is(FontStyle::NO_OUTLINE) ? *fontNoOutline : *fontWithOutline; unsigned texture = usedFont.GetTexture(); if(!texture) return; const GlPoint texSize(usedFont.GetTexSize()); RTTR_Assert(texList.texCoords.size() == texList.vertices.size()); RTTR_Assert(texList.texCoords.size() % 4u == 0); // Vectorizable loop for(unsigned i = 0; i < texList.texCoords.size(); i += 4) { for(int j = 0; j < 4; j++) texList.texCoords[i + j] /= texSize; } glVertexPointer(2, GL_FLOAT, 0, &texList.vertices[0]); glTexCoordPointer(2, GL_FLOAT, 0, &texList.texCoords[0]); VIDEODRIVER.BindTexture(texture); glColor4ub(GetRed(color), GetGreen(color), GetBlue(color), GetAlpha(color)); glDrawArrays(GL_QUADS, 0, texList.vertices.size()); }
void FontCollection::itemize(const uint16_t* string, size_t string_size, FontStyle style, vector<Run>* result) const { const uint32_t langListId = style.getLanguageListId(); int variant = style.getVariant(); const FontFamily* lastFamily = nullptr; Run* run = NULL; if (string_size == 0) { return; } const uint32_t kEndOfString = 0xFFFFFFFF; uint32_t nextCh = 0; uint32_t prevCh = 0; size_t nextUtf16Pos = 0; size_t readLength = 0; U16_NEXT(string, readLength, string_size, nextCh); do { const uint32_t ch = nextCh; const size_t utf16Pos = nextUtf16Pos; nextUtf16Pos = readLength; if (readLength < string_size) { U16_NEXT(string, readLength, string_size, nextCh); } else { nextCh = kEndOfString; } bool shouldContinueRun = false; if (lastFamily != nullptr) { if (isStickyWhitelisted(ch)) { // Continue using existing font as long as it has coverage and is // whitelisted shouldContinueRun = lastFamily->getCoverage().get(ch); } else if (ch == SOFT_HYPHEN || isVariationSelector(ch)) { // Always continue if the character is the soft hyphen or a variation // selector. shouldContinueRun = true; } } if (!shouldContinueRun) { const std::shared_ptr<FontFamily>& family = getFamilyForChar( ch, isVariationSelector(nextCh) ? nextCh : 0, langListId, variant); if (utf16Pos == 0 || family.get() != lastFamily) { size_t start = utf16Pos; // Workaround for combining marks and emoji modifiers until we implement // per-cluster font selection: if a combining mark or an emoji modifier // is found in a different font that also supports the previous // character, attach previous character to the new run. U+20E3 COMBINING // ENCLOSING KEYCAP, used in emoji, is handled properly by this since // it's a combining mark too. if (utf16Pos != 0 && ((U_GET_GC_MASK(ch) & U_GC_M_MASK) != 0 || (isEmojiModifier(ch) && isEmojiBase(prevCh))) && family != nullptr && family->getCoverage().get(prevCh)) { const size_t prevChLength = U16_LENGTH(prevCh); run->end -= prevChLength; if (run->start == run->end) { result->pop_back(); } start -= prevChLength; } result->push_back( {family->getClosestMatch(style), static_cast<int>(start), 0}); run = &result->back(); lastFamily = family.get(); } } prevCh = ch; run->end = nextUtf16Pos; // exclusive } while (nextCh != kEndOfString); }
// Initialize GLUT & OpenSG and set up the scene int main(int argc, char **argv) { // OSG init osgInit(argc, argv); // GLUT init int winid = setupGLUT(&argc, argv); // the connection between GLUT and OpenSG GLUTWindowPtr gwin = GLUTWindow::create(); gwin->setId(winid); gwin->init(); PathHandler paths; paths.push_backPath("."); // create the scene // build a special txf-font with only a little set of characters FontStyle *fontStyle = FontStyleFactory::the().create(paths, argv[1], 1); assert(fontStyle); //((TTFontStyle *) fontStyle)->createTXFMap((UChar8 *) ". fps0123456789"); ((TTFontStyle *) fontStyle)->createTXFMap(); // write it somewhere #if 1 std::ofstream target; target.open("statistics.txf"); fontStyle->dump(target); target.close(); #else ostrstream target; fontStyle->dump(target); #endif #if 1 std::ifstream source; source.open("statistics.txf"); #else #if 0 // Hack, to get the stuff into memory int bufSize = 100000; char *buffer = new char[bufSize]; int numRead; FILE *in = fopen("statistics.txf", "r"); numRead = fread(buffer, 1, bufSize, in); fclose(in); istrstream source(buffer, numRead); #else istrstream source(target.str(), target.pcount()); #endif #endif TXFFont *font = new TXFFont("test.txf", source); font->initFont(); fontText.setSize(1); font->createInstance(&fontText); fontText.setJustifyMajor(MIDDLE_JT); lineVec.push_back("0000.00 fps"); // TXF-Style Texture+Geometry n = Node::create(); txfGeo = Geometry::create(); ImagePtr pTxfImg = Image::create(); if(fontText.fillTXFGeo(*txfGeo, true, lineVec)) { fontText.fillTXFImage(pTxfImg); SimpleTexturedMaterialPtr mat = SimpleTexturedMaterial::create(); beginEditCP(mat); { mat->setImage(pTxfImg); } endEditCP(mat); txfGeo->setMaterial(mat); beginEditCP(n, Node::CoreFieldMask); { n->setCore(txfGeo); } } scene = Node::create(); // add a transformation to make it move trans = Transform::create(); beginEditCP(scene, Node::CoreFieldMask | Node::ChildrenFieldMask); { scene->setCore(trans); scene->addChild(n); } endEditCP(scene, Node::CoreFieldMask | Node::ChildrenFieldMask); // create the SimpleSceneManager helper mgr = new SimpleSceneManager; // tell the manager what to manage mgr->setWindow(gwin); mgr->setRoot(scene); // show the whole scene mgr->showAll(); // GLUT main loop glutMainLoop(); return 0; }