void Nebula::drawLabel(StelPainter& sPainter, float maxMagLabel) { float lim = mag; if (lim > 50) lim = 15.f; // temporary workaround of this bug: https://bugs.launchpad.net/stellarium/+bug/1115035 --AW if (getEnglishName().contains("Pleiades")) lim = 5.f; if (lim>maxMagLabel) return; Vec3f col(labelColor[0], labelColor[1], labelColor[2]); sPainter.setColor(col[0], col[1], col[2], hintsBrightness); float size = getAngularSize(NULL)*M_PI/180.*sPainter.getProjector()->getPixelPerRadAtCenter(); float shift = 4.f + size/1.8f; QString str; if (!nameI18.isEmpty()) str = getNameI18n(); else { if (M_nb > 0) str = QString("M %1").arg(M_nb); else if (C_nb > 0) str = QString("C %1").arg(C_nb); else if (NGC_nb > 0) str = QString("NGC %1").arg(NGC_nb); else if (IC_nb > 0) str = QString("IC %1").arg(IC_nb); } sPainter.drawText(XY[0]+shift, XY[1]+shift, str, 0, 0, 0, false); }
static QString getEnglishName(const QString &familyName) { QString i18n_name; HDC hdc = GetDC( 0 ); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); if(!hfont) { ReleaseDC(0, hdc); return QString(); } HGDIOBJ oldobj = SelectObject( hdc, hfont ); const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' ); // get the name table unsigned char *table = 0; DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 ); if ( bytes == GDI_ERROR ) { // ### Unused variable /* int err = GetLastError(); */ goto error; } table = new unsigned char[bytes]; GetFontData(hdc, name_tag, 0, table, bytes); if ( bytes == GDI_ERROR ) goto error; i18n_name = getEnglishName(table, bytes); error: delete [] table; SelectObject( hdc, oldobj ); DeleteObject( hfont ); ReleaseDC( 0, hdc ); //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); return i18n_name; }
void Nebula::drawHints(StelPainter& sPainter, float maxMagHints) { float lim = mag; if (lim > 50) lim = 15.f; // temporary workaround of this bug: https://bugs.launchpad.net/stellarium/+bug/1115035 --AW if (getEnglishName().contains("Pleiades")) lim = 5.f; if (lim>maxMagHints) return; glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); float lum = 1.f;//qMin(1,4.f/getOnScreenSize(core))*0.8; Vec3f col(circleColor[0]*lum*hintsBrightness, circleColor[1]*lum*hintsBrightness, circleColor[2]*lum*hintsBrightness); sPainter.setColor(col[0], col[1], col[2], 1); switch (nType) { case NebGx: Nebula::texGalaxy->bind(); break; case NebOc: Nebula::texOpenCluster->bind(); break; case NebGc: Nebula::texGlobularCluster->bind(); break; case NebN: Nebula::texDiffuseNebula->bind(); break; case NebPn: Nebula::texPlanetaryNebula->bind(); break; case NebCn: Nebula::texOpenClusterWithNebulosity->bind(); break; default: Nebula::texCircle->bind(); } sPainter.drawSprite2dMode(XY[0], XY[1], 6); }
static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont) { const uchar *data = reinterpret_cast<const uchar *>(fontData.constData()); QList<quint32> offsets = getTrueTypeFontOffsets(data); if (offsets.isEmpty()) return; for (int i = 0; i < offsets.count(); ++i) { const uchar *font = data + offsets.at(i); const uchar *table; quint32 length; getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); if (!table) continue; QString name = getEnglishName(table, length); if (name.isEmpty()) continue; appFont->families << name; FONTSIGNATURE signature; getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); if (table && length >= 86) { // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42); signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46); signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50); signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54); signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78); signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82); } else { memset(&signature, 0, sizeof(signature)); } appFont->signatures << signature; } }
static void addFontToDatabase(QString familyName, const QString &scriptName, TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, int type) { const int script = -1; const QString foundryName; Q_UNUSED(script); bool italic = false; int weight; bool fixed; bool ttf; bool scalable; int size; // QString escript = QString::fromWCharArray(f->elfScript); // qDebug("script=%s", escript.latin1()); NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; italic = tm->tmItalic; weight = tm->tmWeight; // the "@family" fonts are just the same as "family". Ignore them. if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) { QtFontStyle::Key styleKey; styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; styleKey.weight = weightFromInteger(weight); QtFontFamily *family = privateDb()->family(familyName, true); if(ttf && localizedName(familyName) && family->english_name.isEmpty()) family->english_name = getEnglishName(familyName); QtFontFoundry *foundry = family->foundry(foundryName, true); QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); // add fonts windows can generate for us: if (styleKey.weight <= QFont::DemiBold) { QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } if (styleKey.style != QFont::StyleItalic) { QtFontStyle::Key key(styleKey); key.style = QFont::StyleItalic; QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) { QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; key.style = QFont::StyleItalic; QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } family->fixedPitch = fixed; if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) { quint32 unicodeRange[4] = { signature->fsUsb[0], signature->fsUsb[1], signature->fsUsb[2], signature->fsUsb[3] }; #ifdef Q_WS_WINCE if (signature->fsUsb[0] == 0) { // If the unicode ranges bit mask is zero then // EnumFontFamiliesEx failed to determine it properly. // In this case we just pretend that the font supports all languages. unicodeRange[0] = 0xbfffffff; // second most significant bit must be zero unicodeRange[1] = 0xffffffff; unicodeRange[2] = 0xffffffff; unicodeRange[3] = 0xffffffff; } #endif quint32 codePageRange[2] = { signature->fsCsb[0], signature->fsCsb[1] }; QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); for (int i = 0; i < systems.count(); ++i) { QFontDatabase::WritingSystem writingSystem = systems.at(i); // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains // the symbol for Baht, and Windows thus reports that it supports the Thai script. // Since it's the default UI font on this platform, most widgets will be unable to // display Thai text by default. As a temporary work around, we special case Segoe UI // and remove the Thai script from its list of supported writing systems. if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI")) family->writingSystems[writingSystem] = QtFontFamily::Supported; } } else if (!family->writingSystemCheck) { //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1()); if (scriptName == QLatin1String("Western") || scriptName == QLatin1String("Baltic") || scriptName == QLatin1String("Central European") || scriptName == QLatin1String("Turkish") || scriptName == QLatin1String("Vietnamese")) family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Thai")) family->writingSystems[QFontDatabase::Thai] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Symbol") || scriptName == QLatin1String("Other")) family->writingSystems[QFontDatabase::Symbol] = QtFontFamily::Supported; else if (scriptName == QLatin1String("OEM/Dos")) family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; else if (scriptName == QLatin1String("CHINESE_GB2312")) family->writingSystems[QFontDatabase::SimplifiedChinese] = QtFontFamily::Supported; else if (scriptName == QLatin1String("CHINESE_BIG5")) family->writingSystems[QFontDatabase::TraditionalChinese] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Cyrillic")) family->writingSystems[QFontDatabase::Cyrillic] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Hangul")) family->writingSystems[QFontDatabase::Korean] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Hebrew")) family->writingSystems[QFontDatabase::Hebrew] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Greek")) family->writingSystems[QFontDatabase::Greek] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Japanese")) family->writingSystems[QFontDatabase::Japanese] = QtFontFamily::Supported; else if (scriptName == QLatin1String("Arabic")) family->writingSystems[QFontDatabase::Arabic] = QtFontFamily::Supported; } } }
static bool addFontToDatabase(QString familyName, const QString &scriptName, const TEXTMETRIC *textmetric, const FONTSIGNATURE *signature, int type) { typedef QPair<QString, QStringList> FontKey; // the "@family" fonts are just the same as "family". Ignore them. if (familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QStringLiteral("WST_"))) return false; const int separatorPos = familyName.indexOf(QStringLiteral("::")); const QString faceName = separatorPos != -1 ? familyName.left(separatorPos) : familyName; const QString fullName = separatorPos != -1 ? familyName.mid(separatorPos + 2) : QString(); static const int SMOOTH_SCALABLE = 0xffff; const QString foundryName; // No such concept. const NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; const bool fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); const bool ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); const bool scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; const QFont::Weight weight = weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT if (QWindowsContext::verboseFonts > 2) { QDebug nospace = qDebug().nospace(); nospace << __FUNCTION__ << faceName << fullName << scriptName << "TTF=" << ttf; if (type & DEVICE_FONTTYPE) nospace << " DEVICE"; if (type & RASTER_FONTTYPE) nospace << " RASTER"; if (type & TRUETYPE_FONTTYPE) nospace << " TRUETYPE"; nospace << " scalable=" << scalable << " Size=" << size << " Style=" << style << " Weight=" << weight << " stretch=" << stretch; } #endif QString englishName; if (ttf && localizedName(faceName)) englishName = getEnglishName(faceName); QSupportedWritingSystems writingSystems; if (type & TRUETYPE_FONTTYPE) { quint32 unicodeRange[4] = { signature->fsUsb[0], signature->fsUsb[1], signature->fsUsb[2], signature->fsUsb[3] }; quint32 codePageRange[2] = { signature->fsCsb[0], signature->fsCsb[1] }; writingSystems = QBasicFontDatabase::determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains // the symbol for Baht, and Windows thus reports that it supports the Thai script. // Since it's the default UI font on this platform, most widgets will be unable to // display Thai text by default. As a temporary work around, we special case Segoe UI // and remove the Thai script from its list of supported writing systems. if (writingSystems.supported(QFontDatabase::Thai) && faceName == QStringLiteral("Segoe UI")) writingSystems.setSupported(QFontDatabase::Thai, false); } else { const QFontDatabase::WritingSystem ws = writingSystemFromScript(scriptName); if (ws != QFontDatabase::Any) writingSystems.setSupported(ws); } #ifndef Q_OS_WINCE const QSettings fontRegistry(QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), QSettings::NativeFormat); static QVector<FontKey> allFonts; if (allFonts.isEmpty()) { const QStringList allKeys = fontRegistry.allKeys(); allFonts.reserve(allKeys.size()); const QString trueType = QStringLiteral("(TrueType)"); const QRegExp sizeListMatch(QStringLiteral("\\s(\\d+,)+\\d+")); foreach (const QString &key, allKeys) { QString realKey = key; realKey.remove(trueType); realKey.remove(sizeListMatch); QStringList fonts; const QStringList fontNames = realKey.trimmed().split(QLatin1Char('&')); foreach (const QString &fontName, fontNames) fonts.push_back(fontName.trimmed()); allFonts.push_back(FontKey(key, fonts)); } }
void Nebula::drawLabel(StelPainter& sPainter, float maxMagLabel) { float lim = mag; if (lim > 50) lim = 15.f; // temporary workaround of this bug: https://bugs.launchpad.net/stellarium/+bug/1115035 --AW if (getEnglishName().contains("Pleiades")) lim = 5.f; // Dark nebulae. Not sure how to assess visibility from opacity? --GZ if (nType==NebDn) { // GZ: ad-hoc visibility formula: assuming good visibility if objects of mag9 are visible, "usual" opacity 5 and size 30', better visibility (discernability) comes with higher opacity and larger size, // 9-(opac-5)-2*(angularSize-0.5) if (angularSize>0 && mag<50) lim = 15.0f - mag - 2.0f*angularSize; else lim = 9.0f; } else if (nType==NebHII || nType==NebHa) lim=9.0f; if (lim>maxMagLabel) return; Vec3d win; // Check visibility of DSO labels if (!(sPainter.getProjector()->projectCheck(XYZ, win))) return; Vec3f col(labelColor[0], labelColor[1], labelColor[2]); sPainter.setColor(col[0], col[1], col[2], hintsBrightness); float size = getAngularSize(NULL)*M_PI/180.*sPainter.getProjector()->getPixelPerRadAtCenter(); float shift = 4.f + (drawHintProportional ? size : size/1.8f); QString str; if (!nameI18.isEmpty()) str = getNameI18n(); else { // On screen label: one only, priority as given here. NGC should win over Sharpless. (GZ) if (M_nb > 0) str = QString("M %1").arg(M_nb); else if (C_nb > 0) str = QString("C %1").arg(C_nb); else if (NGC_nb > 0) str = QString("NGC %1").arg(NGC_nb); else if (IC_nb > 0) str = QString("IC %1").arg(IC_nb); else if (B_nb > 0) str = QString("B %1").arg(B_nb); else if (Sh2_nb > 0) str = QString("Sh 2-%1").arg(Sh2_nb); else if (VdB_nb > 0) str = QString("VdB %1").arg(VdB_nb); else if (RCW_nb > 0) str = QString("RCW %1").arg(RCW_nb); else if (LDN_nb > 0) str = QString("LDN %1").arg(LDN_nb); else if (LBN_nb > 0) str = QString("LBN %1").arg(LBN_nb); else if (Cr_nb > 0) str = QString("Cr %1").arg(Cr_nb); else if (Mel_nb > 0) str = QString("Mel %1").arg(Mel_nb); } sPainter.drawText(XY[0]+shift, XY[1]+shift, str, 0, 0, 0, false); }
void Nebula::drawHints(StelPainter& sPainter, float maxMagHints) { float lim = mag; if (lim > 50) lim = 15.f; // temporary workaround of this bug: https://bugs.launchpad.net/stellarium/+bug/1115035 --AW if (getEnglishName().contains("Pleiades")) lim = 5.f; // Dark nebulae. Not sure how to assess visibility from opacity? --GZ if (nType==NebDn) { // GZ: ad-hoc visibility formula: assuming good visibility if objects of mag9 are visible, "usual" opacity 5 and size 30', better visibility (discernability) comes with higher opacity and larger size, // 9-(opac-5)-2*(angularSize-0.5) if (angularSize>0 && mag<50) lim = 15.0f - mag - 2.0f*angularSize; else lim = 9.0f; } else if (nType==NebHII || nType==NebHa) { // artificially increase visibility of (most) Sharpless objects? No magnitude recorded:-( lim=9.0f; } if (lim>maxMagHints) return; Vec3d win; // Check visibility of DSO hints if (!(sPainter.getProjector()->projectCheck(XYZ, win))) return; glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); float lum = 1.f;//qMin(1,4.f/getOnScreenSize(core))*0.8; Vec3f col(circleColor[0]*lum*hintsBrightness, circleColor[1]*lum*hintsBrightness, circleColor[2]*lum*hintsBrightness); sPainter.setColor(col[0], col[1], col[2], 1); switch (nType) { case NebGx: Nebula::texGalaxy->bind(); break; case NebOc: Nebula::texOpenCluster->bind(); break; case NebGc: Nebula::texGlobularCluster->bind(); break; case NebN: case NebHII: case NebRn: Nebula::texDiffuseNebula->bind(); break; case NebPn: Nebula::texPlanetaryNebula->bind(); break; case NebDn: Nebula::texDarkNebula->bind(); break; case NebCn: Nebula::texOpenClusterWithNebulosity->bind(); break; default: Nebula::texCircle->bind(); } if (drawHintProportional) { float size = getAngularSize(NULL)*M_PI/180.*sPainter.getProjector()->getPixelPerRadAtCenter(); sPainter.drawSprite2dMode(XY[0], XY[1], qMax(6.0f,size)); } else sPainter.drawSprite2dMode(XY[0], XY[1], 6.0f); }
// Draw the Comet and all the related infos : name, circle etc... GZ: Taken from Planet.cpp 2013-11-05 and extended void Comet::draw(StelCore* core, float maxMagLabels, const QFont& planetNameFont) { if (hidden) return; if (getEnglishName() == core->getCurrentLocation().planetName) { // GZ moved this up. Maybe even don't do that? E.g., draw tail while riding the comet? Decide later. return; } // The CometOrbit is in fact available in userDataPtr! CometOrbit* orbit=(CometOrbit*)userDataPtr; Q_ASSERT(orbit); if (!orbit->objectDateValid(core->getJDay())) return; // out of useful date range. This allows having hundreds of comet elements. if (orbit->getUpdateTails()){ // Compute lengths and orientations from orbit object, but only if required. // TODO: This part should possibly be moved to another thread to keep draw() free from too much computation. Vec2f tailFactors=getComaDiameterAndTailLengthAU(); float gasTailEndRadius=qMax(tailFactors[0], 0.025f*tailFactors[1]) ; // This avoids too slim gas tails for bright comets like Hale-Bopp. float gasparameter=gasTailEndRadius*gasTailEndRadius/(2.0f*tailFactors[1]); // parabola formula: z=r²/2p, so p=r²/2z // The dust tail is thicker and usually shorter. The factors can be configured in the elements. float dustparameter=gasTailEndRadius*gasTailEndRadius*dustTailWidthFactor*dustTailWidthFactor/(2.0f*dustTailLengthFactor*tailFactors[1]); // Find valid parameters to create paraboloid vertex arrays: dustTail, gasTail. computeParabola(gasparameter, gasTailEndRadius, -0.5f*gasparameter, gastailVertexArr, gastailTexCoordArr, gastailIndices); // This was for a rotated straight parabola: //computeParabola(dustparameter, 2.0f*tailFactors[0], -0.5f*dustparameter, dusttailVertexArr, dusttailTexCoordArr, dusttailIndices); // Now we make a skewed parabola. Skew factor 15 (last arg) ad-hoc/empirical. TBD later: Find physically correct solution. computeParabola(dustparameter, dustTailWidthFactor*gasTailEndRadius, -0.5f*dustparameter, dusttailVertexArr, gastailTexCoordArr, gastailIndices, 25.0f*orbit->getVelocity().length()); // Note that we use a diameter larger than what the formula returns. A scale factor of 1.2 is ad-hoc/empirical (GZ), but may look better. computeComa(1.0f*tailFactors[0]); orbit->setUpdateTails(false); // don't update until position has been recalculated elsewhere } Mat4d mat = Mat4d::translation(eclipticPos) * rotLocalToParent; /* // We can remove that - a Comet has no parent except for the sun... PlanetP p = parent; while (p && p->parent) { mat = Mat4d::translation(p->eclipticPos) * mat * p->rotLocalToParent; p = p->parent; } */ // This removed totally the Planet shaking bug!!! StelProjector::ModelViewTranformP transfo = core->getHeliocentricEclipticModelViewTransform(); transfo->combine(mat); // Compute the 2D position and check if in the screen const StelProjectorP prj = core->getProjection(transfo); float screenSz = getAngularSize(core)*M_PI/180.*prj->getPixelPerRadAtCenter(); float viewport_left = prj->getViewportPosX(); float viewport_bottom = prj->getViewportPosY(); if (prj->project(Vec3d(0), screenPos) && screenPos[1]>viewport_bottom - screenSz && screenPos[1] < viewport_bottom + prj->getViewportHeight()+screenSz && screenPos[0]>viewport_left - screenSz && screenPos[0] < viewport_left + prj->getViewportWidth() + screenSz) { // Draw the name, and the circle if it's not too close from the body it's turning around // this prevents name overlapping (ie for jupiter satellites) float ang_dist = 300.f*atan(getEclipticPos().length()/getEquinoxEquatorialPos(core).length())/core->getMovementMgr()->getCurrentFov(); // if (ang_dist==0.f) ang_dist = 1.f; // if ang_dist == 0, the Planet is sun.. --> GZ: we can remove it. // by putting here, only draw orbit if Comet is visible for clarity drawOrbit(core); // TODO - fade in here also... if (flagLabels && ang_dist>0.25 && maxMagLabels>getVMagnitude(core)) { labelsFader=true; } else { labelsFader=false; } drawHints(core, planetNameFont); draw3dModel(core,transfo,screenSz); } // tails should also be drawn if core is off-screen... drawTail(core,transfo,true); // gas tail drawTail(core,transfo,false); // dust tail //Coma: this is just a fan disk tilted towards the observer;-) drawComa(core, transfo); return; }