float VirtualFont::getOffsetX(const LineLayout &layout, Alignment align) const { switch (align) { case ALIGN_MIDDLE: return -0.5f * getAdvance(layout); case ALIGN_RIGHT: return -getAdvance(layout); default: return 0; } }
float Font::getAdvance( const char c) { char string[2]; string[0] = c; string[1] = 0; return getAdvance(string); }
float Font::getAdvance( const wchar_t c) { wchar_t string[2]; string[0] = c; string[1] = 0; return getAdvance(string); }
void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_F) { int rpm = ENGINE(rpmCalculator.rpmValue); sparkDwell = getSparkDwell(rpm PASS_ENGINE_PARAMETER); dwellAngle = sparkDwell / getOneDegreeTimeMs(rpm); iatFuelCorrection = getIatCorrection(iat PASS_ENGINE_PARAMETER); cltFuelCorrection = getCltCorrection(clt PASS_ENGINE_PARAMETER); engineNoiseHipLevel = interpolate2d(rpm, engineConfiguration->knockNoiseRpmBins, engineConfiguration->knockNoise, ENGINE_NOISE_CURVE_SIZE); baroCorrection = getBaroCorrection(PASS_ENGINE_PARAMETER_F); injectionOffset = getinjectionOffset(rpm PASS_ENGINE_PARAMETER); float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); timingAdvance = getAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER); if (engineConfiguration->algorithm == LM_SPEED_DENSITY) { float coolantC = ENGINE(engineState.clt); float intakeC = ENGINE(engineState.iat); float tps = getTPS(PASS_ENGINE_PARAMETER_F); tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC)); float map = getMap(); /** * *0.01 because of https://sourceforge.net/p/rusefi/tickets/153/ */ currentVE = baroCorrection * veMap.getValue(map, rpm) * 0.01; targerAFR = afrMap.getValue(map, rpm); } else { baseTableFuel = getBaseTableFuel(engineConfiguration, rpm, engineLoad); } }
float Font::getAdvance(uint16_t charcode, float fontSize) const { MetricsData::const_iterator itr = mMetrics.find(charcode); if (itr != mMetrics.end()) return getAdvance(itr->second, fontSize); return 0.0f; }
float ofxTextAlign::getWidth(const char *str, bool single_line) { float ret = 0; float tmp = 0; const char *ptr = str; char prev = -1; while(*ptr != '\0' && !(single_line && *ptr == '\n')) { switch(*ptr) { case '\n': ret = max(ret, tmp); tmp = 0; prev = -1; break; default: if(prev != -1) { tmp += getKerning(*ptr, prev); } prev = *ptr; tmp += getAdvance(*ptr); break; } ++ptr; } return max(ret, tmp); }
// Devanagari ka+virama+ka TEST(Measurement, getRunAdvance_kka) { const float unligated[] = {30.0, 0.0, 30.0}; EXPECT_EQ(0.0, getAdvance(unligated, "| U+0915 U+094D U+0915")); EXPECT_EQ(30.0, getAdvance(unligated, "U+0915 | U+094D U+0915")); EXPECT_EQ(30.0, getAdvance(unligated, "U+0915 U+094D | U+0915")); EXPECT_EQ(60.0, getAdvance(unligated, "U+0915 U+094D U+0915 |")); const float ligated[] = {30.0, 0.0, 0.0}; EXPECT_EQ(0.0, getAdvance(ligated, "| U+0915 U+094D U+0915")); EXPECT_EQ(30.0, getAdvance(ligated, "U+0915 | U+094D U+0915")); EXPECT_EQ(30.0, getAdvance(ligated, "U+0915 U+094D | U+0915")); EXPECT_EQ(30.0, getAdvance(ligated, "U+0915 U+094D U+0915 |")); }
const char* ofxTextAlign::drawLine(const char *str, float x, float y) { const char *ptr = str; int letter_count = getLetterCount(str, true); float extra_spacing = letter_count>1?(getDrawWidth(str, true)-getWidth(str, true))/(float)(letter_count-1):0; while(*ptr != '\0') { if(*ptr=='\n') { ++ptr; break; } float interval = getAdvance(*ptr) + getKerning(*(ptr+1), *ptr) + extra_spacing; ptr = drawChar(ptr, x, y); x += interval; } return ptr; }
// Latin fi TEST(Measurement, getRunAdvance_fi) { const float unligated[] = {30.0, 20.0}; EXPECT_EQ(0.0, getAdvance(unligated, "| 'f' 'i'")); EXPECT_EQ(30.0, getAdvance(unligated, "'f' | 'i'")); EXPECT_EQ(50.0, getAdvance(unligated, "'f' 'i' |")); const float ligated[] = {40.0, 0.0}; EXPECT_EQ(0.0, getAdvance(ligated, "| 'f' 'i'")); EXPECT_EQ(20.0, getAdvance(ligated, "'f' | 'i'")); EXPECT_EQ(40.0, getAdvance(ligated, "'f' 'i' |")); }
float ofxTextAlign::getOffsetX(const char *str, unsigned int flags, bool single_line) { unsigned int flag = flags&HORIZONTAL_ALIGN_MASK; if(HORIZONTAL_ALIGN_LEFT == flag) { return 0; } else if(single_line && getLetterCount(str, true) < 2) { float width = getAdvance(*str); switch(flag) { case HORIZONTAL_ALIGN_CENTER: return -width/2.f; case HORIZONTAL_ALIGN_RIGHT: return -width; } } else { float width = getDrawWidth(str, single_line); switch(flag) { case HORIZONTAL_ALIGN_CENTER: return -width/2.f; case HORIZONTAL_ALIGN_RIGHT: return -width; } } return 0; }
static void printAdvance(int rpm, int maf100) { float advance = getAdvance(rpm, maf100 / 100.0); print("advance for %d rpm %d maf100: %f\r\n", rpm, maf100, advance); }
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData( FontHandle fontHandle, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) { // Assuming that on average, the ASCII representation of an advance plus // a space is 8 characters and the ASCII representation of a glyph id is 3 // characters, then the following cut offs for using different range types // apply: // The cost of stopping and starting the range is 7 characers // a. Removing 4 0's or don't care's is a win // The cost of stopping and starting the range plus a run is 22 // characters // b. Removing 3 repeating advances is a win // c. Removing 2 repeating advances and 3 don't cares is a win // When not currently in a range the cost of a run over a range is 16 // characaters, so: // d. Removing a leading 0/don't cares is a win because it is omitted // e. Removing 2 repeating advances is a win SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result; SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange; SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = NULL; Data lastAdvance = kInvalidAdvance; int repeatedAdvances = 0; int wildCardsInRun = 0; int trailingWildCards = 0; uint32_t subsetIndex = 0; // Limit the loop count to glyph id ranges provided. int firstIndex = 0; int lastIndex = num_glyphs; if (subsetGlyphIDs) { firstIndex = static_cast<int>(subsetGlyphIDs[0]); lastIndex = static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; } curRange = appendRange(&result, firstIndex); for (int gId = firstIndex; gId <= lastIndex; gId++) { Data advance = kInvalidAdvance; if (gId < lastIndex) { // Get glyph id only when subset is NULL, or the id is in subset. if (!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) { SkAssertResult(getAdvance(fontHandle, gId, &advance)); ++subsetIndex; } else { advance = kDontCareAdvance; } } if (advance == lastAdvance) { repeatedAdvances++; trailingWildCards = 0; } else if (advance == kDontCareAdvance) { wildCardsInRun++; trailingWildCards++; } else if (curRange->fAdvance.count() == repeatedAdvances + 1 + wildCardsInRun) { // All in run. if (lastAdvance == 0) { resetRange(curRange, gId); trailingWildCards = 0; } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) { finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } else { if (lastAdvance == 0 && repeatedAdvances + 1 + wildCardsInRun >= 4) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) { finishRange(curRange, gId - trailingWildCards - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (lastAdvance != 0 && (repeatedAdvances + 1 >= 3 || (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); curRange = appendRange(&curRange->fNext, gId - repeatedAdvances - wildCardsInRun - 1); curRange->fAdvance.append(1, &lastAdvance); finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } curRange->fAdvance.append(1, &advance); if (advance != kDontCareAdvance) { lastAdvance = advance; } } if (curRange->fStartId == lastIndex) { SkASSERT(prevRange); SkASSERT(prevRange->fNext->fStartId == lastIndex); prevRange->fNext.reset(); } else { finishRange(curRange, lastIndex - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); } return result.release(); }
void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) { efitick_t nowNt = getTimeNowNt(); if (ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE)) { crankingTime = nowNt; timeSinceCranking = 0.0f; } else { timeSinceCranking = nowNt - crankingTime; } updateAuxValves(PASS_ENGINE_PARAMETER_SIGNATURE); int rpm = ENGINE(rpmCalculator).getRpm(PASS_ENGINE_PARAMETER_SIGNATURE); sparkDwell = getSparkDwell(rpm PASS_ENGINE_PARAMETER_SUFFIX); dwellAngle = sparkDwell / getOneDegreeTimeMs(rpm); if (hasAfrSensor(PASS_ENGINE_PARAMETER_SIGNATURE)) { engine->sensors.currentAfr = getAfr(PASS_ENGINE_PARAMETER_SIGNATURE); } // todo: move this into slow callback, no reason for IAT corr to be here iatFuelCorrection = getIatFuelCorrection(engine->sensors.iat PASS_ENGINE_PARAMETER_SUFFIX); // todo: move this into slow callback, no reason for CLT corr to be here if (boardConfiguration->useWarmupPidAfr && engine->sensors.clt < engineConfiguration->warmupAfrThreshold) { if (rpm < 200) { cltFuelCorrection = 1; warmupAfrPid.reset(); } else { cltFuelCorrection = warmupAfrPid.getValue(warmupTargetAfr, engine->sensors.currentAfr, 1); } #if ! EFI_UNIT_TEST || defined(__DOXYGEN__) if (engineConfiguration->debugMode == DBG_WARMUP_ENRICH) { tsOutputChannels.debugFloatField1 = warmupTargetAfr; warmupAfrPid.postState(&tsOutputChannels); } #endif } else { cltFuelCorrection = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); } // update fuel consumption states fuelConsumption.update(nowNt PASS_ENGINE_PARAMETER_SUFFIX); // Fuel cut-off isn't just 0 or 1, it can be tapered fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX); // post-cranking fuel enrichment. // for compatibility reasons, apply only if the factor is greater than zero (0.01 margin used) if (engineConfiguration->postCrankingFactor > 0.01f) { // convert to microsecs and then to seconds float timeSinceCrankingInSecs = NT2US(timeSinceCranking) / 1000000.0f; // use interpolation for correction taper postCrankingFuelCorrection = interpolateClamped(0.0f, engineConfiguration->postCrankingFactor, engineConfiguration->postCrankingDurationSec, 1.0f, timeSinceCrankingInSecs); } else { postCrankingFuelCorrection = 1.0f; } cltTimingCorrection = getCltTimingCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); engineNoiseHipLevel = interpolate2d("knock", rpm, engineConfiguration->knockNoiseRpmBins, engineConfiguration->knockNoise, ENGINE_NOISE_CURVE_SIZE); baroCorrection = getBaroCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); injectionOffset = getinjectionOffset(rpm PASS_ENGINE_PARAMETER_SUFFIX); float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_SIGNATURE); timingAdvance = getAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER_SUFFIX); if (engineConfiguration->fuelAlgorithm == LM_SPEED_DENSITY) { float coolantC = ENGINE(sensors.clt); float intakeC = ENGINE(sensors.iat); float tps = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE); tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC PASS_ENGINE_PARAMETER_SUFFIX)); float map = getMap(); /** * *0.01 because of https://sourceforge.net/p/rusefi/tickets/153/ */ float rawVe = veMap.getValue(rpm, map); // get VE from the separate table for Idle if (CONFIG(useSeparateVeForIdle)) { float idleVe = interpolate2d("idleVe", rpm, config->idleVeBins, config->idleVe, IDLE_VE_CURVE_SIZE); // interpolate between idle table and normal (running) table using TPS threshold rawVe = interpolateClamped(0.0f, idleVe, boardConfiguration->idlePidDeactivationTpsThreshold, rawVe, tps); } currentVE = baroCorrection * rawVe * 0.01; targetAFR = afrMap.getValue(rpm, map); } else { baseTableFuel = getBaseTableFuel(rpm, engineLoad); } }
void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_F) { int rpm = ENGINE(rpmCalculator.rpmValue); efitick_t nowNt = getTimeNowNt(); if (isCrankingR(rpm)) { crankingTime = nowNt; } else { timeSinceCranking = nowNt - crankingTime; } sparkDwell = getSparkDwell(rpm PASS_ENGINE_PARAMETER); dwellAngle = sparkDwell / getOneDegreeTimeMs(rpm); // todo: move this into slow callback, no reason for IAT corr to be here iatFuelCorrection = getIatCorrection(iat PASS_ENGINE_PARAMETER); // todo: move this into slow callback, no reason for CLT corr to be here if (boardConfiguration->useWarmupPidAfr && clt < engineConfiguration->warmupAfrThreshold) { if (rpm < 200) { cltFuelCorrection = 1; warmupAfrPid.reset(); } else { cltFuelCorrection = warmupAfrPid.getValue(warmupTargetAfr, getAfr(PASS_ENGINE_PARAMETER_F), 1); } #if ! EFI_UNIT_TEST || defined(__DOXYGEN__) if (engineConfiguration->debugMode == WARMUP_ENRICH) { tsOutputChannels.debugFloatField1 = warmupTargetAfr; warmupAfrPid.postState(&tsOutputChannels); } #endif } else { cltFuelCorrection = getCltFuelCorrection(clt PASS_ENGINE_PARAMETER); } cltTimingCorrection = getCltTimingCorrection(clt PASS_ENGINE_PARAMETER); engineNoiseHipLevel = interpolate2d(rpm, engineConfiguration->knockNoiseRpmBins, engineConfiguration->knockNoise, ENGINE_NOISE_CURVE_SIZE); baroCorrection = getBaroCorrection(PASS_ENGINE_PARAMETER_F); injectionOffset = getinjectionOffset(rpm PASS_ENGINE_PARAMETER); float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); timingAdvance = getAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER); if (engineConfiguration->fuelAlgorithm == LM_SPEED_DENSITY) { float coolantC = ENGINE(engineState.clt); float intakeC = ENGINE(engineState.iat); float tps = getTPS(PASS_ENGINE_PARAMETER_F); tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC PASS_ENGINE_PARAMETER)); float map = getMap(); /** * *0.01 because of https://sourceforge.net/p/rusefi/tickets/153/ */ currentVE = baroCorrection * veMap.getValue(rpm, map) * 0.01; targetAFR = afrMap.getValue(rpm, map); } else { baseTableFuel = getBaseTableFuel(engineConfiguration, rpm, engineLoad); } }
void SkAdvancedTypefaceMetrics::setGlyphWidths( FontHandle fontHandle, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(FontHandle fontHandle, int gId, int16_t* data)) { // Assuming that on average, the ASCII representation of an advance plus // a space is 8 characters and the ASCII representation of a glyph id is 3 // characters, then the following cut offs for using different range types // apply: // The cost of stopping and starting the range is 7 characers // a. Removing 4 0's or don't care's is a win // The cost of stopping and starting the range plus a run is 22 // characters // b. Removing 3 repeating advances is a win // c. Removing 2 repeating advances and 3 don't cares is a win // When not currently in a range the cost of a run over a range is 16 // characaters, so: // d. Removing a leading 0/don't cares is a win because it is omitted // e. Removing 2 repeating advances is a win WidthRange* prevRange = nullptr; int16_t lastAdvance = kInvalidAdvance; int repeatedAdvances = 0; int wildCardsInRun = 0; int trailingWildCards = 0; uint32_t subsetIndex = 0; // Limit the loop count to glyph id ranges provided. int firstIndex = 0; int lastIndex = num_glyphs; if (subsetGlyphIDs) { firstIndex = static_cast<int>(subsetGlyphIDs[0]); lastIndex = static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; } WidthRange curRange(firstIndex); for (int gId = firstIndex; gId <= lastIndex; gId++) { int16_t advance = kInvalidAdvance; if (gId < lastIndex) { // Get glyph id only when subset is nullptr, or the id is in subset. SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex])); if (!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) { SkAssertResult(getAdvance(fontHandle, gId, &advance)); ++subsetIndex; } else { advance = kDontCareAdvance; } } if (advance == lastAdvance) { repeatedAdvances++; trailingWildCards = 0; } else if (advance == kDontCareAdvance) { wildCardsInRun++; trailingWildCards++; } else if (curRange.fAdvance.count() == repeatedAdvances + 1 + wildCardsInRun) { // All in run. if (lastAdvance == 0) { curRange.fStartId = gId; // reset curRange.fAdvance.setCount(0); trailingWildCards = 0; } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) { FinishRange(&curRange, gId - 1, WidthRange::kRun); prevRange = fGlyphWidths.emplace_back(std::move(curRange)); curRange = WidthRange(gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } else { if (lastAdvance == 0 && repeatedAdvances + 1 + wildCardsInRun >= 4) { FinishRange(&curRange, gId - repeatedAdvances - wildCardsInRun - 2, WidthRange::kRange); prevRange = fGlyphWidths.emplace_back(std::move(curRange)); curRange = WidthRange(gId); trailingWildCards = 0; } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) { FinishRange(&curRange, gId - trailingWildCards - 1, WidthRange::kRange); prevRange = fGlyphWidths.emplace_back(std::move(curRange)); curRange = WidthRange(gId); trailingWildCards = 0; } else if (lastAdvance != 0 && (repeatedAdvances + 1 >= 3 || (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) { FinishRange(&curRange, gId - repeatedAdvances - wildCardsInRun - 2, WidthRange::kRange); (void)fGlyphWidths.emplace_back(std::move(curRange)); curRange = WidthRange(gId - repeatedAdvances - wildCardsInRun - 1); curRange.fAdvance.append(1, &lastAdvance); FinishRange(&curRange, gId - 1, WidthRange::kRun); prevRange = fGlyphWidths.emplace_back(std::move(curRange)); curRange = WidthRange(gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } curRange.fAdvance.append(1, &advance); if (advance != kDontCareAdvance) { lastAdvance = advance; } } if (curRange.fStartId == lastIndex) { SkASSERT(prevRange); if (!prevRange) { fGlyphWidths.reset(); return; // https://crbug.com/567031 } } else { FinishRange(&curRange, lastIndex - 1, WidthRange::kRange); fGlyphWidths.emplace_back(std::move(curRange)); } }