<commit_before>/*
 * Copyright (C) 2007, 2008, 2010, 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/css/CSSFontFaceSource.h"

#include "RuntimeEnabledFeatures.h"
#include "core/css/CSSCustomFontData.h"
#include "core/css/CSSFontFace.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/SimpleFontData.h"
#include "public/platform/Platform.h"
#include "wtf/CurrentTime.h"

#if ENABLE(SVG_FONTS)
#include "SVGNames.h"
#include "core/svg/SVGFontData.h"
#include "core/svg/SVGFontElement.h"
#include "core/svg/SVGFontFaceElement.h"
#endif

namespace WebCore {

CSSFontFaceSource::CSSFontFaceSource(const String& str, FontResource* font)
    : m_string(str)
    , m_font(font)
    , m_face(0)
#if ENABLE(SVG_FONTS)
    , m_hasExternalSVGFont(false)
#endif
{
    if (m_font)
        m_font->addClient(this);
}

CSSFontFaceSource::~CSSFontFaceSource()
{
    if (m_font)
        m_font->removeClient(this);
    pruneTable();
}

void CSSFontFaceSource::pruneTable()
{
    if (m_fontDataTable.isEmpty())
        return;

    for (FontDataTable::iterator it = m_fontDataTable.begin(); it != m_fontDataTable.end(); ++it) {
        SimpleFontData* fontData = it->value.get();
        if (fontData && fontData->customFontData())
            fontData->customFontData()->clearCSSFontFaceSource();
    }
    m_fontDataTable.clear();
}

bool CSSFontFaceSource::isLocal() const
{
    if (m_font)
        return false;
#if ENABLE(SVG_FONTS)
    if (m_svgFontFaceElement)
        return false;
#endif
    return true;
}

bool CSSFontFaceSource::isLoading() const
{
    if (m_font)
        return !m_font->stillNeedsLoad() && !m_font->isLoaded();
    return false;
}

bool CSSFontFaceSource::isLoaded() const
{
    if (m_font)
        return m_font->isLoaded();
    return true;
}

bool CSSFontFaceSource::isValid() const
{
    if (m_font)
        return !m_font->errorOccurred();
    return true;
}

void CSSFontFaceSource::didStartFontLoad(FontResource*)
{
    // Avoid duplicated reports when multiple CSSFontFaceSource are registered
    // at this FontResource.
    if (!m_fontDataTable.isEmpty())
        m_histograms.loadStarted();
}

void CSSFontFaceSource::fontLoaded(FontResource*)
{
    if (!m_fontDataTable.isEmpty())
        m_histograms.recordRemoteFont(m_font.get());

    pruneTable();
    if (m_face)
        m_face->fontLoaded(this);
}

PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription)
{
    // If the font hasn't loaded or an error occurred, then we've got nothing.
    if (!isValid())
        return 0;

    if (isLocal()) {
        // We're local. Just return a SimpleFontData from the normal cache.
        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
        RefPtr<SimpleFontData> fontData = FontCache::fontCache()->getFontData(fontDescription, m_string, true);
        m_histograms.recordLocalFont(fontData);
        return fontData;
    }

    // See if we have a mapping in our FontData cache.
    AtomicString emptyFontFamily = "";
    FontCacheKey key = fontDescription.cacheKey(emptyFontFamily);

    RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(key.hash(), 0).iterator->value;
    if (fontData)
        return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.

    // If we are still loading, then we let the system pick a font.
    if (isLoaded()) {
        if (m_font) {
#if ENABLE(SVG_FONTS)
            if (m_hasExternalSVGFont) {
                // For SVG fonts parse the external SVG document, and extract the <font> element.
                if (!m_font->ensureSVGFontData())
                    return 0;

                if (!m_externalSVGFontElement) {
                    String fragmentIdentifier;
                    size_t start = m_string.find('#');
                    if (start != kNotFound)
                        fragmentIdentifier = m_string.string().substring(start + 1);
                    m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier);
                }

                if (!m_externalSVGFontElement)
                    return 0;

                SVGFontFaceElement* fontFaceElement = 0;

                // Select first <font-face> child
                for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) {
                    if (fontChild->hasTagName(SVGNames::font_faceTag)) {
                        fontFaceElement = toSVGFontFaceElement(fontChild);
                        break;
                    }
                }

                if (fontFaceElement) {
                    if (!m_svgFontFaceElement) {
                        // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement.
                        // Use the imported <font-face> tag as referencing font-face element for these cases.
                        m_svgFontFaceElement = fontFaceElement;
                    }

                    fontData = SimpleFontData::create(
                        SVGFontData::create(fontFaceElement),
                        fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(),
                        fontDescription.isSyntheticItalic());
                }
            } else
#endif
            {
                // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
                if (!m_font->ensureCustomFontData())
                    return 0;

                fontData = SimpleFontData::create(
                    m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
                        fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create(false));
            }
        } else {
#if ENABLE(SVG_FONTS)
            // In-Document SVG Fonts
            if (m_svgFontFaceElement) {
                fontData = SimpleFontData::create(
                    SVGFontData::create(m_svgFontFaceElement.get()),
                    fontDescription.effectiveFontSize(),
                    fontDescription.isSyntheticBold(),
                    fontDescription.isSyntheticItalic());
            }
#endif
        }
    } else {
        // This temporary font is not retained and should not be returned.
        FontCachePurgePreventer fontCachePurgePreventer;
        SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
        if (!temporaryFont) {
            ASSERT_NOT_REACHED();
            return 0;
        }
        RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(true);
        cssFontData->setCSSFontFaceSource(this);
        fontData = SimpleFontData::create(temporaryFont->platformData(), cssFontData);
    }

    return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.
}

#if ENABLE(SVG_FONTS)
SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
{
    return m_svgFontFaceElement.get();
}

void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element)
{
    m_svgFontFaceElement = element;
}

bool CSSFontFaceSource::isSVGFontFaceSource() const
{
    return m_svgFontFaceElement || m_hasExternalSVGFont;
}
#endif

bool CSSFontFaceSource::ensureFontData()
{
    if (!m_font)
        return false;
#if ENABLE(SVG_FONTS)
    if (m_hasExternalSVGFont)
        return m_font->ensureSVGFontData();
#endif
    return m_font->ensureCustomFontData();
}

bool CSSFontFaceSource::isLocalFontAvailable(const FontDescription& fontDescription)
{
    if (!isLocal())
        return false;
    return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, m_string);
}

void CSSFontFaceSource::beginLoadIfNeeded()
{
    if (m_face && m_font)
        m_face->beginLoadIfNeeded(this);
}

void CSSFontFaceSource::FontLoadHistograms::loadStarted()
{
    if (!m_loadStartTime)
        m_loadStartTime = currentTimeMS();
}

void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess)
{
    if (!m_loadStartTime) {
        blink::Platform::current()->histogramEnumeration("WebFont.LocalFontUsed", loadSuccess ? 1 : 0, 2);
        m_loadStartTime = -1; // Do not count this font again.
    }
}

void CSSFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font)
{
    if (m_loadStartTime > 0 && font && !font->isLoading()) {
        int duration = static_cast<int>(currentTimeMS() - m_loadStartTime);
        blink::Platform::current()->histogramCustomCounts(histogramName(font), duration, 0, 10000, 50);
        m_loadStartTime = -1;

        enum { Miss, Hit, DataUrl, CacheHitEnumMax };
        int histogramValue = font->url().protocolIsData() ? DataUrl
            : font->response().wasCached() ? Hit
            : Miss;
        blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax);
    }
}

const char* CSSFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font)
{
    if (font->errorOccurred())
        return "WebFont.DownloadTime.LoadError";

    unsigned size = font->encodedSize();
    if (size < 10 * 1024)
        return "WebFont.DownloadTime.0.Under10KB";
    if (size < 50 * 1024)
        return "WebFont.DownloadTime.1.10KBTo50KB";
    if (size < 100 * 1024)
        return "WebFont.DownloadTime.2.50KBTo100KB";
    if (size < 1024 * 1024)
        return "WebFont.DownloadTime.3.100KBTo1MB";
    return "WebFont.DownloadTime.4.Over1MB";
}

}
<commit_msg>Revert of Handle null return value for getLastResortFallbackFont (https://codereview.chromium.org/150103014/)<commit_after>/*
 * Copyright (C) 2007, 2008, 2010, 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "core/css/CSSFontFaceSource.h"

#include "RuntimeEnabledFeatures.h"
#include "core/css/CSSCustomFontData.h"
#include "core/css/CSSFontFace.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/FontDescription.h"
#include "platform/fonts/SimpleFontData.h"
#include "public/platform/Platform.h"
#include "wtf/CurrentTime.h"

#if ENABLE(SVG_FONTS)
#include "SVGNames.h"
#include "core/svg/SVGFontData.h"
#include "core/svg/SVGFontElement.h"
#include "core/svg/SVGFontFaceElement.h"
#endif

namespace WebCore {

CSSFontFaceSource::CSSFontFaceSource(const String& str, FontResource* font)
    : m_string(str)
    , m_font(font)
    , m_face(0)
#if ENABLE(SVG_FONTS)
    , m_hasExternalSVGFont(false)
#endif
{
    if (m_font)
        m_font->addClient(this);
}

CSSFontFaceSource::~CSSFontFaceSource()
{
    if (m_font)
        m_font->removeClient(this);
    pruneTable();
}

void CSSFontFaceSource::pruneTable()
{
    if (m_fontDataTable.isEmpty())
        return;

    for (FontDataTable::iterator it = m_fontDataTable.begin(); it != m_fontDataTable.end(); ++it) {
        SimpleFontData* fontData = it->value.get();
        if (fontData && fontData->customFontData())
            fontData->customFontData()->clearCSSFontFaceSource();
    }
    m_fontDataTable.clear();
}

bool CSSFontFaceSource::isLocal() const
{
    if (m_font)
        return false;
#if ENABLE(SVG_FONTS)
    if (m_svgFontFaceElement)
        return false;
#endif
    return true;
}

bool CSSFontFaceSource::isLoading() const
{
    if (m_font)
        return !m_font->stillNeedsLoad() && !m_font->isLoaded();
    return false;
}

bool CSSFontFaceSource::isLoaded() const
{
    if (m_font)
        return m_font->isLoaded();
    return true;
}

bool CSSFontFaceSource::isValid() const
{
    if (m_font)
        return !m_font->errorOccurred();
    return true;
}

void CSSFontFaceSource::didStartFontLoad(FontResource*)
{
    // Avoid duplicated reports when multiple CSSFontFaceSource are registered
    // at this FontResource.
    if (!m_fontDataTable.isEmpty())
        m_histograms.loadStarted();
}

void CSSFontFaceSource::fontLoaded(FontResource*)
{
    if (!m_fontDataTable.isEmpty())
        m_histograms.recordRemoteFont(m_font.get());

    pruneTable();
    if (m_face)
        m_face->fontLoaded(this);
}

PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription)
{
    // If the font hasn't loaded or an error occurred, then we've got nothing.
    if (!isValid())
        return 0;

    if (isLocal()) {
        // We're local. Just return a SimpleFontData from the normal cache.
        // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
        RefPtr<SimpleFontData> fontData = FontCache::fontCache()->getFontData(fontDescription, m_string, true);
        m_histograms.recordLocalFont(fontData);
        return fontData;
    }

    // See if we have a mapping in our FontData cache.
    AtomicString emptyFontFamily = "";
    FontCacheKey key = fontDescription.cacheKey(emptyFontFamily);

    RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(key.hash(), 0).iterator->value;
    if (fontData)
        return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.

    // If we are still loading, then we let the system pick a font.
    if (isLoaded()) {
        if (m_font) {
#if ENABLE(SVG_FONTS)
            if (m_hasExternalSVGFont) {
                // For SVG fonts parse the external SVG document, and extract the <font> element.
                if (!m_font->ensureSVGFontData())
                    return 0;

                if (!m_externalSVGFontElement) {
                    String fragmentIdentifier;
                    size_t start = m_string.find('#');
                    if (start != kNotFound)
                        fragmentIdentifier = m_string.string().substring(start + 1);
                    m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier);
                }

                if (!m_externalSVGFontElement)
                    return 0;

                SVGFontFaceElement* fontFaceElement = 0;

                // Select first <font-face> child
                for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) {
                    if (fontChild->hasTagName(SVGNames::font_faceTag)) {
                        fontFaceElement = toSVGFontFaceElement(fontChild);
                        break;
                    }
                }

                if (fontFaceElement) {
                    if (!m_svgFontFaceElement) {
                        // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement.
                        // Use the imported <font-face> tag as referencing font-face element for these cases.
                        m_svgFontFaceElement = fontFaceElement;
                    }

                    fontData = SimpleFontData::create(
                        SVGFontData::create(fontFaceElement),
                        fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(),
                        fontDescription.isSyntheticItalic());
                }
            } else
#endif
            {
                // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
                if (!m_font->ensureCustomFontData())
                    return 0;

                fontData = SimpleFontData::create(
                    m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(),
                        fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(),
                        fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create(false));
            }
        } else {
#if ENABLE(SVG_FONTS)
            // In-Document SVG Fonts
            if (m_svgFontFaceElement) {
                fontData = SimpleFontData::create(
                    SVGFontData::create(m_svgFontFaceElement.get()),
                    fontDescription.effectiveFontSize(),
                    fontDescription.isSyntheticBold(),
                    fontDescription.isSyntheticItalic());
            }
#endif
        }
    } else {
        // This temporary font is not retained and should not be returned.
        FontCachePurgePreventer fontCachePurgePreventer;
        SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
        RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(true);
        cssFontData->setCSSFontFaceSource(this);
        fontData = SimpleFontData::create(temporaryFont->platformData(), cssFontData);
    }

    return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable.
}

#if ENABLE(SVG_FONTS)
SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
{
    return m_svgFontFaceElement.get();
}

void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element)
{
    m_svgFontFaceElement = element;
}

bool CSSFontFaceSource::isSVGFontFaceSource() const
{
    return m_svgFontFaceElement || m_hasExternalSVGFont;
}
#endif

bool CSSFontFaceSource::ensureFontData()
{
    if (!m_font)
        return false;
#if ENABLE(SVG_FONTS)
    if (m_hasExternalSVGFont)
        return m_font->ensureSVGFontData();
#endif
    return m_font->ensureCustomFontData();
}

bool CSSFontFaceSource::isLocalFontAvailable(const FontDescription& fontDescription)
{
    if (!isLocal())
        return false;
    return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, m_string);
}

void CSSFontFaceSource::beginLoadIfNeeded()
{
    if (m_face && m_font)
        m_face->beginLoadIfNeeded(this);
}

void CSSFontFaceSource::FontLoadHistograms::loadStarted()
{
    if (!m_loadStartTime)
        m_loadStartTime = currentTimeMS();
}

void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess)
{
    if (!m_loadStartTime) {
        blink::Platform::current()->histogramEnumeration("WebFont.LocalFontUsed", loadSuccess ? 1 : 0, 2);
        m_loadStartTime = -1; // Do not count this font again.
    }
}

void CSSFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font)
{
    if (m_loadStartTime > 0 && font && !font->isLoading()) {
        int duration = static_cast<int>(currentTimeMS() - m_loadStartTime);
        blink::Platform::current()->histogramCustomCounts(histogramName(font), duration, 0, 10000, 50);
        m_loadStartTime = -1;

        enum { Miss, Hit, DataUrl, CacheHitEnumMax };
        int histogramValue = font->url().protocolIsData() ? DataUrl
            : font->response().wasCached() ? Hit
            : Miss;
        blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax);
    }
}

const char* CSSFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font)
{
    if (font->errorOccurred())
        return "WebFont.DownloadTime.LoadError";

    unsigned size = font->encodedSize();
    if (size < 10 * 1024)
        return "WebFont.DownloadTime.0.Under10KB";
    if (size < 50 * 1024)
        return "WebFont.DownloadTime.1.10KBTo50KB";
    if (size < 100 * 1024)
        return "WebFont.DownloadTime.2.50KBTo100KB";
    if (size < 1024 * 1024)
        return "WebFont.DownloadTime.3.100KBTo1MB";
    return "WebFont.DownloadTime.4.Over1MB";
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "os-release.hpp"
#include "File.hpp"
#include "utils.hpp"
#include "libdnf/dnf-context.h"

#include <algorithm>
#include <array>
#include <map>
#include <rpm/rpmlib.h>
#include <sstream>
#include <string>
#include <vector>

namespace libdnf {

// whitelists used for sanity-checking the os-release data when constructing a
// User-Agent string (to avoid reporting rare systems or platforms that could
// be tracked)
std::map<std::string, std::vector<std::string>> distros = {
    // taken from the fedora-release.spec file
    { "Fedora", { "cinnamon", "cloud", "container", "coreos", "iot", "kde",
                  "matecompiz", "server", "silverblue", "snappy", "soas",
                  "workstation", "xfce" } },
};
std::array<const std::string, 1> canons = { "Linux" };

std::map<std::string, std::string> getOsReleaseData(const std::vector<std::string> & paths)
{
    std::map<std::string, std::string> result;

    // find the first existing file path
    auto it = std::find_if(paths.begin(), paths.end(), libdnf::filesystem::exists);
    if (it == paths.end())
        throw std::runtime_error("os-release file not found");
    std::string path = *it;

    auto file = libdnf::File::newFile(path);
    file->open("r");
    std::string line;
    while (file->readLine(line)) {
        // remove trailing spaces and newline
        line.erase(line.find_last_not_of(" \n") + 1);

        // skip empty lines
        if (line.empty()) continue;
        // skip comments
        if (line.front() == '#') continue;

        // split string by '=' into key and value
        auto pos = line.find('=');
        if (pos == line.npos)
            throw std::runtime_error("Invalid format (missing '='): " + line);
        auto key    = string::trim(line.substr(0, pos));
        auto value  = string::trim(line.substr(pos + 1, line.length()));

        // remove quotes if present
        if (!value.empty() && value.front() == '"' && value.back() == '"') {
            value = value.substr(1, value.length() - 2);
        }

        result.insert({key, value});
    }
    return result;
}

static void initLibRpm()
{
    static bool libRpmInitiated{false};
    if (libRpmInitiated) return;
    if (rpmReadConfigFiles(NULL, NULL) != 0) {
        throw std::runtime_error("failed to read rpm config files\n");
    }
    libRpmInitiated = true;
}

static std::string getBaseArch()
{
    const char *value;
    initLibRpm();
    rpmGetArchInfo(&value, NULL);
    value = find_base_arch(value);
    return value ? std::string(value) : "";
}

static std::string getCanonOs()
{
    const char *value;
    initLibRpm();
    rpmGetOsInfo(&value, NULL);
    return value;
}

std::string getUserAgent(const std::map<std::string, std::string> & osReleaseData)
{
    std::ostringstream oss;
    std::string distro = osReleaseData.at("NAME");
    std::string canon = getCanonOs();
    std::string arch = getBaseArch();

    // basic libdnf version string
    oss << USER_AGENT;

    // consult our whitelists
    if (distros.find(distro) == distros.end()
        || std::find(canons.begin(), canons.end(), canon) == canons.end()
        || arch.empty())
        return oss.str();

    // append OS data
    oss << " (" << distro << " " << osReleaseData.at("VERSION_ID") << "; ";
    std::string variant = "generic";
    if (osReleaseData.find("VARIANT_ID") != osReleaseData.end()) {
        std::string value = osReleaseData.at("VARIANT_ID");
        auto list = distros.at(distro);
        if (std::find(list.begin(), list.end(), value) != list.end())
            variant = value;
    }
    oss << variant << "; " << canon << "." << arch << ")";

    return oss.str();
}

}
<commit_msg>[user-agent] Add "generic" variant to whitelist<commit_after>/*
 * Copyright (C) 2019 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "os-release.hpp"
#include "File.hpp"
#include "utils.hpp"
#include "libdnf/dnf-context.h"

#include <algorithm>
#include <array>
#include <map>
#include <rpm/rpmlib.h>
#include <sstream>
#include <string>
#include <vector>

namespace libdnf {

// whitelists used for sanity-checking the os-release data when constructing a
// User-Agent string (to avoid reporting rare systems or platforms that could
// be tracked)
std::map<std::string, std::vector<std::string>> distros = {
    // taken from the {fedora,generic}-release.spec files
    { "Fedora", { "cinnamon", "cloud", "container", "coreos", "generic", "iot",
                  "kde", "matecompiz", "server", "silverblue", "snappy", "soas",
                  "workstation", "xfce" } },
};
std::array<const std::string, 1> canons = { "Linux" };

std::map<std::string, std::string> getOsReleaseData(const std::vector<std::string> & paths)
{
    std::map<std::string, std::string> result;

    // find the first existing file path
    auto it = std::find_if(paths.begin(), paths.end(), libdnf::filesystem::exists);
    if (it == paths.end())
        throw std::runtime_error("os-release file not found");
    std::string path = *it;

    auto file = libdnf::File::newFile(path);
    file->open("r");
    std::string line;
    while (file->readLine(line)) {
        // remove trailing spaces and newline
        line.erase(line.find_last_not_of(" \n") + 1);

        // skip empty lines
        if (line.empty()) continue;
        // skip comments
        if (line.front() == '#') continue;

        // split string by '=' into key and value
        auto pos = line.find('=');
        if (pos == line.npos)
            throw std::runtime_error("Invalid format (missing '='): " + line);
        auto key    = string::trim(line.substr(0, pos));
        auto value  = string::trim(line.substr(pos + 1, line.length()));

        // remove quotes if present
        if (!value.empty() && value.front() == '"' && value.back() == '"') {
            value = value.substr(1, value.length() - 2);
        }

        result.insert({key, value});
    }
    return result;
}

static void initLibRpm()
{
    static bool libRpmInitiated{false};
    if (libRpmInitiated) return;
    if (rpmReadConfigFiles(NULL, NULL) != 0) {
        throw std::runtime_error("failed to read rpm config files\n");
    }
    libRpmInitiated = true;
}

static std::string getBaseArch()
{
    const char *value;
    initLibRpm();
    rpmGetArchInfo(&value, NULL);
    value = find_base_arch(value);
    return value ? std::string(value) : "";
}

static std::string getCanonOs()
{
    const char *value;
    initLibRpm();
    rpmGetOsInfo(&value, NULL);
    return value;
}

std::string getUserAgent(const std::map<std::string, std::string> & osReleaseData)
{
    std::ostringstream oss;
    std::string distro = osReleaseData.at("NAME");
    std::string canon = getCanonOs();
    std::string arch = getBaseArch();

    // basic libdnf version string
    oss << USER_AGENT;

    // consult our whitelists
    if (distros.find(distro) == distros.end()
        || std::find(canons.begin(), canons.end(), canon) == canons.end()
        || arch.empty())
        return oss.str();

    // append OS data
    oss << " (" << distro << " " << osReleaseData.at("VERSION_ID") << "; ";
    std::string variant = "generic";
    if (osReleaseData.find("VARIANT_ID") != osReleaseData.end()) {
        std::string value = osReleaseData.at("VARIANT_ID");
        auto list = distros.at(distro);
        if (std::find(list.begin(), list.end(), value) != list.end())
            variant = value;
    }
    oss << variant << "; " << canon << "." << arch << ")";

    return oss.str();
}

}
<|endoftext|>


<commit_before><commit_msg>Removing wrong test.<commit_after><|endoftext|>


<commit_before><commit_msg>Added member variables selection<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <set>
#include <map>
using namespace std;

class RangeModule {
    typedef set<pair<int,int>> t_mpi;
    t_mpi ranges_;
public:
    RangeModule() {

    }

    void addRange(int left, int right) {
        if (ranges_.empty()) {
            ranges_.insert(make_pair(left,right));
            return;
        }
        t_mpi::iterator it = ranges_.upper_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        int a = left;
        int b = right;
        while (it != ranges_.end() && it->first <= right) {
            if (left > it->first) a = it->first;
            if (right < it->second) b = it->second;
            ranges_.erase(it++);
        }
        ranges_.insert(make_pair(a,b));
    }

    bool queryRange(int left, int right) {
        if (ranges_.empty()) return false;
        t_mpi::iterator it = ranges_.lower_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        while (it != ranges_.end() && it->first <= right) {
            if (left >= it->first) left = it->second;
            if (right <= it->second) right = it->first;
            ++it;
        }
        return right <= left;
    }

    void removeRange(int left, int right) {
        if (ranges_.empty()) return;
        t_mpi::iterator it = ranges_.lower_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        vector<pair<int,int>> tmp;
        while (it != ranges_.end() && it->first <= right) {
            if (left > it->first) tmp.push_back(make_pair(it->first, left));
            if (right < it->second) tmp.push_back(make_pair(right, it->second));
            ranges_.erase(it++);
        }
        for (int i=0; i<tmp.size(); ++i) {
            ranges_.insert(tmp[i]);
        }
    }

    void dump() {
        for (t_mpi::iterator it=ranges_.begin(); it!=ranges_.end(); ++it) {
            cout << "[" << it->first << ", " << it->second << ")" << endl;
        }
        cout << "-------------" << endl;
    }
};

int main() {
    RangeModule rm;
    rm.addRange(10,20);
    rm.dump();
    rm.removeRange(14,16);
    rm.dump();
    cout << rm.queryRange(10,14) << endl; // 1
    cout << rm.queryRange(13,15) << endl; // 0
    cout << rm.queryRange(16,17) << endl; // 1
}

<commit_msg>Update hard_range_module.cpp<commit_after>#include <iostream>
#include <vector>
#include <set>
#include <map>
using namespace std;

class RangeModule {
    typedef set<pair<int,int>> t_mpi;
    t_mpi ranges_;
public:
    RangeModule() {

    }

    void addRange(int left, int right) {
        if (ranges_.empty()) {
            ranges_.insert(make_pair(left,right));
            return;
        }
        t_mpi::iterator it = ranges_.upper_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        int a = left;
        int b = right;
        while (it != ranges_.end() && it->first <= right) {
            if (left > it->first) a = it->first;
            if (right < it->second) b = it->second;
            ranges_.erase(it++);
        }
        if (a < b) ranges_.insert(make_pair(a,b));
    }

    bool queryRange(int left, int right) {
        if (ranges_.empty()) return false;
        t_mpi::iterator it = ranges_.lower_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        while (it != ranges_.end() && it->first <= right) {
            if (left >= it->first) left = it->second;
            if (right <= it->second) right = it->first;
            ++it;
        }
        return right <= left;
    }

    void removeRange(int left, int right) {
        if (ranges_.empty()) return;
        t_mpi::iterator it = ranges_.lower_bound(make_pair(left, left));
        if (it != ranges_.begin() && (--it)->second < left) ++it;
        vector<pair<int,int>> tmp;
        while (it != ranges_.end() && it->first <= right) {
            if (left > it->first) tmp.push_back(make_pair(it->first, left));
            if (right < it->second) tmp.push_back(make_pair(right, it->second));
            ranges_.erase(it++);
        }
        for (int i=0; i<tmp.size(); ++i) {
            ranges_.insert(tmp[i]);
        }
    }

    void dump() {
        for (t_mpi::iterator it=ranges_.begin(); it!=ranges_.end(); ++it) {
            cout << "[" << it->first << ", " << it->second << ")" << endl;
        }
        cout << "-------------" << endl;
    }
};

int main() {
    RangeModule rm;
    rm.addRange(10,20);
    rm.dump();
    rm.removeRange(14,16);
    rm.dump();
    cout << rm.queryRange(10,14) << endl; // 1
    cout << rm.queryRange(13,15) << endl; // 0
    cout << rm.queryRange(16,17) << endl; // 1
}

<|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/entity/contents/filters/blend_filter_contents.h"

#include <array>
#include <memory>
#include <optional>

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"

namespace impeller {

BlendFilterContents::BlendFilterContents() {
  SetBlendMode(BlendMode::kSourceOver);
}

BlendFilterContents::~BlendFilterContents() = default;

using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
    ContentContext::*)(ContentContextOptions) const;

template <typename TPipeline>
static std::optional<Snapshot> AdvancedBlend(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Rect& coverage,
    std::optional<Color> foreground_color,
    PipelineProc pipeline_proc) {
  using VS = typename TPipeline::VertexShader;
  using FS = typename TPipeline::FragmentShader;

  //----------------------------------------------------------------------------
  /// Handle inputs.
  ///

  const size_t total_inputs =
      inputs.size() + (foreground_color.has_value() ? 1 : 0);
  if (total_inputs < 2) {
    return std::nullopt;
  }

  auto dst_snapshot = inputs[0]->GetSnapshot(renderer, entity);
  if (!dst_snapshot.has_value()) {
    return std::nullopt;
  }
  auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage);
  if (!maybe_dst_uvs.has_value()) {
    return std::nullopt;
  }
  auto dst_uvs = maybe_dst_uvs.value();

  std::optional<Snapshot> src_snapshot;
  std::array<Point, 4> src_uvs;
  if (!foreground_color.has_value()) {
    src_snapshot = inputs[1]->GetSnapshot(renderer, entity);
    if (!src_snapshot.has_value()) {
      return std::nullopt;
    }
    auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
    if (!maybe_src_uvs.has_value()) {
      return std::nullopt;
    }
    src_uvs = maybe_src_uvs.value();
  }

  //----------------------------------------------------------------------------
  /// Render to texture.
  ///

  ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
                                                 RenderPass& pass) {
    auto& host_buffer = pass.GetTransientsBuffer();

    auto size = pass.GetRenderTargetSize();
    VertexBufferBuilder<typename VS::PerVertexData> vtx_builder;
    vtx_builder.AddVertices({
        {Point(0, 0), dst_uvs[0], src_uvs[0]},
        {Point(size.width, 0), dst_uvs[1], src_uvs[1]},
        {Point(size.width, size.height), dst_uvs[3], src_uvs[3]},
        {Point(0, 0), dst_uvs[0], src_uvs[0]},
        {Point(size.width, size.height), dst_uvs[3], src_uvs[3]},
        {Point(0, size.height), dst_uvs[2], src_uvs[2]},
    });
    auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);

    auto options = OptionsFromPassAndEntity(pass, entity);
    std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
        std::invoke(pipeline_proc, renderer, options);

    Command cmd;
    cmd.label = "Advanced Blend Filter";
    cmd.BindVertices(vtx_buffer);
    cmd.pipeline = std::move(pipeline);

    typename FS::BlendInfo blend_info;

    auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({});
    FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler);
    blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();

    if (foreground_color.has_value()) {
      blend_info.color_factor = 1;
      blend_info.color = foreground_color.value();
      // This texture will not be sampled from due to the color factor. But
      // this is present so that validation doesn't trip on a missing
      // binding.
      FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, sampler);
    } else {
      blend_info.color_factor = 0;
      FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, sampler);
      blend_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
    }
    auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
    FS::BindBlendInfo(cmd, blend_uniform);

    typename VS::FrameInfo frame_info;
    frame_info.mvp = Matrix::MakeOrthographic(size);

    auto uniform_view = host_buffer.EmplaceUniform(frame_info);
    VS::BindFrameInfo(cmd, uniform_view);
    pass.AddCommand(cmd);

    return true;
  };

  auto out_texture = renderer.MakeSubpass(ISize(coverage.size), callback);
  if (!out_texture) {
    return std::nullopt;
  }
  out_texture->SetLabel("Advanced Blend Filter Texture");

  return Snapshot{.texture = out_texture,
                  .transform = Matrix::MakeTranslation(coverage.origin),
                  .sampler_descriptor = dst_snapshot->sampler_descriptor};
}

static std::optional<Snapshot> PipelineBlend(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Rect& coverage,
    BlendMode pipeline_blend,
    std::optional<Color> foreground_color) {
  using VS = BlendPipeline::VertexShader;
  using FS = BlendPipeline::FragmentShader;

  ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
                                                 RenderPass& pass) {
    auto& host_buffer = pass.GetTransientsBuffer();

    auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({});

    Command cmd;
    cmd.label = "Pipeline Blend Filter";
    auto options = OptionsFromPass(pass);

    auto add_blend_command = [&](std::optional<Snapshot> input) {
      if (!input.has_value()) {
        return false;
      }
      auto input_coverage = input->GetCoverage();
      if (!input_coverage.has_value()) {
        return false;
      }

      FS::BindTextureSamplerSrc(cmd, input->texture, sampler);

      auto size = input->texture->GetSize();
      VertexBufferBuilder<VS::PerVertexData> vtx_builder;
      vtx_builder.AddVertices({
          {Point(0, 0), Point(0, 0)},
          {Point(size.width, 0), Point(1, 0)},
          {Point(size.width, size.height), Point(1, 1)},
          {Point(0, 0), Point(0, 0)},
          {Point(size.width, size.height), Point(1, 1)},
          {Point(0, size.height), Point(0, 1)},
      });
      auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
      cmd.BindVertices(vtx_buffer);

      VS::FrameInfo frame_info;
      frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
                       Matrix::MakeTranslation(-coverage.origin) *
                       input->transform;
      FS::FragInfo frag_info;
      frag_info.texture_sampler_y_coord_scale =
          input->texture->GetYCoordScale();
      FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
      VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));

      pass.AddCommand(cmd);
      return true;
    };

    // Draw the first texture using kSource.

    options.blend_mode = BlendMode::kSource;
    cmd.pipeline = renderer.GetBlendPipeline(options);
    if (!add_blend_command(inputs[0]->GetSnapshot(renderer, entity))) {
      return true;
    }

    // Write subsequent textures using the selected blend mode.

    if (inputs.size() >= 2) {
      options.blend_mode = pipeline_blend;
      cmd.pipeline = renderer.GetBlendPipeline(options);

      for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
           texture_i++) {
        auto input = texture_i->get()->GetSnapshot(renderer, entity);
        if (!add_blend_command(input)) {
          return true;
        }
      }
    }

    // If a foreground color is set, blend it in.

    if (foreground_color.has_value()) {
      auto contents = std::make_shared<SolidColorContents>();
      contents->SetGeometry(Geometry::MakePath(
          PathBuilder{}
              .AddRect(Rect::MakeSize(pass.GetRenderTargetSize()))
              .TakePath()));
      contents->SetColor(foreground_color.value());

      Entity foreground_entity;
      foreground_entity.SetBlendMode(pipeline_blend);
      foreground_entity.SetContents(contents);
      if (!foreground_entity.Render(renderer, pass)) {
        return false;
      }
    }

    return true;
  };

  auto out_texture = renderer.MakeSubpass(ISize(coverage.size), callback);
  if (!out_texture) {
    return std::nullopt;
  }
  out_texture->SetLabel("Pipeline Blend Filter Texture");

  return Snapshot{
      .texture = out_texture,
      .transform = Matrix::MakeTranslation(coverage.origin),
      .sampler_descriptor =
          inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor};
}

#define BLEND_CASE(mode)                                                  \
  case BlendMode::k##mode:                                                \
    advanced_blend_proc_ = [](const FilterInput::Vector& inputs,          \
                              const ContentContext& renderer,             \
                              const Entity& entity, const Rect& coverage, \
                              std::optional<Color> fg_color) {            \
      PipelineProc p = &ContentContext::GetBlend##mode##Pipeline;         \
      return AdvancedBlend<BlendScreenPipeline>(inputs, renderer, entity, \
                                                coverage, fg_color, p);   \
    };                                                                    \
    break;

void BlendFilterContents::SetBlendMode(BlendMode blend_mode) {
  if (blend_mode > Entity::kLastAdvancedBlendMode) {
    VALIDATION_LOG << "Invalid blend mode " << static_cast<int>(blend_mode)
                   << " assigned to BlendFilterContents.";
  }

  blend_mode_ = blend_mode;

  if (blend_mode > Entity::kLastPipelineBlendMode) {
    switch (blend_mode) {
      BLEND_CASE(Screen)
      BLEND_CASE(Overlay)
      BLEND_CASE(Darken)
      BLEND_CASE(Lighten)
      BLEND_CASE(ColorDodge)
      BLEND_CASE(ColorBurn)
      BLEND_CASE(HardLight)
      BLEND_CASE(SoftLight)
      BLEND_CASE(Difference)
      BLEND_CASE(Exclusion)
      BLEND_CASE(Multiply)
      BLEND_CASE(Hue)
      BLEND_CASE(Saturation)
      BLEND_CASE(Color)
      BLEND_CASE(Luminosity)
      default:
        FML_UNREACHABLE();
    }
  }
}

void BlendFilterContents::SetForegroundColor(std::optional<Color> color) {
  foreground_color_ = color;
}

std::optional<Snapshot> BlendFilterContents::RenderFilter(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Matrix& effect_transform,
    const Rect& coverage) const {
  if (inputs.empty()) {
    return std::nullopt;
  }

  if (inputs.size() == 1 && !foreground_color_.has_value()) {
    // Nothing to blend.
    return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource,
                         std::nullopt);
  }

  if (blend_mode_ <= Entity::kLastPipelineBlendMode) {
    return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_,
                         foreground_color_);
  }

  if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
    return advanced_blend_proc_(inputs, renderer, entity, coverage,
                                foreground_color_);
  }
  FML_UNREACHABLE();
}

}  // namespace impeller
<commit_msg>Fix failure case for advanced blend when source snapshot has no coverage (#36655)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "impeller/entity/contents/filters/blend_filter_contents.h"

#include <array>
#include <memory>
#include <optional>

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"

namespace impeller {

BlendFilterContents::BlendFilterContents() {
  SetBlendMode(BlendMode::kSourceOver);
}

BlendFilterContents::~BlendFilterContents() = default;

using PipelineProc = std::shared_ptr<Pipeline<PipelineDescriptor>> (
    ContentContext::*)(ContentContextOptions) const;

template <typename TPipeline>
static std::optional<Snapshot> AdvancedBlend(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Rect& coverage,
    std::optional<Color> foreground_color,
    PipelineProc pipeline_proc) {
  using VS = typename TPipeline::VertexShader;
  using FS = typename TPipeline::FragmentShader;

  //----------------------------------------------------------------------------
  /// Handle inputs.
  ///

  const size_t total_inputs =
      inputs.size() + (foreground_color.has_value() ? 1 : 0);
  if (total_inputs < 2) {
    return std::nullopt;
  }

  auto dst_snapshot = inputs[0]->GetSnapshot(renderer, entity);
  if (!dst_snapshot.has_value()) {
    return std::nullopt;
  }
  auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage);
  if (!maybe_dst_uvs.has_value()) {
    return std::nullopt;
  }
  auto dst_uvs = maybe_dst_uvs.value();

  std::optional<Snapshot> src_snapshot;
  std::array<Point, 4> src_uvs;
  if (!foreground_color.has_value()) {
    src_snapshot = inputs[1]->GetSnapshot(renderer, entity);
    if (!src_snapshot.has_value()) {
      return dst_snapshot;
    }
    auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
    if (!maybe_src_uvs.has_value()) {
      return dst_snapshot;
    }
    src_uvs = maybe_src_uvs.value();
  }

  //----------------------------------------------------------------------------
  /// Render to texture.
  ///

  ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
                                                 RenderPass& pass) {
    auto& host_buffer = pass.GetTransientsBuffer();

    auto size = pass.GetRenderTargetSize();
    VertexBufferBuilder<typename VS::PerVertexData> vtx_builder;
    vtx_builder.AddVertices({
        {Point(0, 0), dst_uvs[0], src_uvs[0]},
        {Point(size.width, 0), dst_uvs[1], src_uvs[1]},
        {Point(size.width, size.height), dst_uvs[3], src_uvs[3]},
        {Point(0, 0), dst_uvs[0], src_uvs[0]},
        {Point(size.width, size.height), dst_uvs[3], src_uvs[3]},
        {Point(0, size.height), dst_uvs[2], src_uvs[2]},
    });
    auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);

    auto options = OptionsFromPassAndEntity(pass, entity);
    std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline =
        std::invoke(pipeline_proc, renderer, options);

    Command cmd;
    cmd.label = "Advanced Blend Filter";
    cmd.BindVertices(vtx_buffer);
    cmd.pipeline = std::move(pipeline);

    typename FS::BlendInfo blend_info;

    auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({});
    FS::BindTextureSamplerDst(cmd, dst_snapshot->texture, sampler);
    blend_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();

    if (foreground_color.has_value()) {
      blend_info.color_factor = 1;
      blend_info.color = foreground_color.value();
      // This texture will not be sampled from due to the color factor. But
      // this is present so that validation doesn't trip on a missing
      // binding.
      FS::BindTextureSamplerSrc(cmd, dst_snapshot->texture, sampler);
    } else {
      blend_info.color_factor = 0;
      FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, sampler);
      blend_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale();
    }
    auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
    FS::BindBlendInfo(cmd, blend_uniform);

    typename VS::FrameInfo frame_info;
    frame_info.mvp = Matrix::MakeOrthographic(size);

    auto uniform_view = host_buffer.EmplaceUniform(frame_info);
    VS::BindFrameInfo(cmd, uniform_view);
    pass.AddCommand(cmd);

    return true;
  };

  auto out_texture = renderer.MakeSubpass(ISize(coverage.size), callback);
  if (!out_texture) {
    return std::nullopt;
  }
  out_texture->SetLabel("Advanced Blend Filter Texture");

  return Snapshot{.texture = out_texture,
                  .transform = Matrix::MakeTranslation(coverage.origin),
                  .sampler_descriptor = dst_snapshot->sampler_descriptor};
}

static std::optional<Snapshot> PipelineBlend(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Rect& coverage,
    BlendMode pipeline_blend,
    std::optional<Color> foreground_color) {
  using VS = BlendPipeline::VertexShader;
  using FS = BlendPipeline::FragmentShader;

  ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
                                                 RenderPass& pass) {
    auto& host_buffer = pass.GetTransientsBuffer();

    auto sampler = renderer.GetContext()->GetSamplerLibrary()->GetSampler({});

    Command cmd;
    cmd.label = "Pipeline Blend Filter";
    auto options = OptionsFromPass(pass);

    auto add_blend_command = [&](std::optional<Snapshot> input) {
      if (!input.has_value()) {
        return false;
      }
      auto input_coverage = input->GetCoverage();
      if (!input_coverage.has_value()) {
        return false;
      }

      FS::BindTextureSamplerSrc(cmd, input->texture, sampler);

      auto size = input->texture->GetSize();
      VertexBufferBuilder<VS::PerVertexData> vtx_builder;
      vtx_builder.AddVertices({
          {Point(0, 0), Point(0, 0)},
          {Point(size.width, 0), Point(1, 0)},
          {Point(size.width, size.height), Point(1, 1)},
          {Point(0, 0), Point(0, 0)},
          {Point(size.width, size.height), Point(1, 1)},
          {Point(0, size.height), Point(0, 1)},
      });
      auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
      cmd.BindVertices(vtx_buffer);

      VS::FrameInfo frame_info;
      frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
                       Matrix::MakeTranslation(-coverage.origin) *
                       input->transform;
      FS::FragInfo frag_info;
      frag_info.texture_sampler_y_coord_scale =
          input->texture->GetYCoordScale();
      FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
      VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));

      pass.AddCommand(cmd);
      return true;
    };

    // Draw the first texture using kSource.

    options.blend_mode = BlendMode::kSource;
    cmd.pipeline = renderer.GetBlendPipeline(options);
    if (!add_blend_command(inputs[0]->GetSnapshot(renderer, entity))) {
      return true;
    }

    // Write subsequent textures using the selected blend mode.

    if (inputs.size() >= 2) {
      options.blend_mode = pipeline_blend;
      cmd.pipeline = renderer.GetBlendPipeline(options);

      for (auto texture_i = inputs.begin() + 1; texture_i < inputs.end();
           texture_i++) {
        auto input = texture_i->get()->GetSnapshot(renderer, entity);
        if (!add_blend_command(input)) {
          return true;
        }
      }
    }

    // If a foreground color is set, blend it in.

    if (foreground_color.has_value()) {
      auto contents = std::make_shared<SolidColorContents>();
      contents->SetGeometry(Geometry::MakePath(
          PathBuilder{}
              .AddRect(Rect::MakeSize(pass.GetRenderTargetSize()))
              .TakePath()));
      contents->SetColor(foreground_color.value());

      Entity foreground_entity;
      foreground_entity.SetBlendMode(pipeline_blend);
      foreground_entity.SetContents(contents);
      if (!foreground_entity.Render(renderer, pass)) {
        return false;
      }
    }

    return true;
  };

  auto out_texture = renderer.MakeSubpass(ISize(coverage.size), callback);
  if (!out_texture) {
    return std::nullopt;
  }
  out_texture->SetLabel("Pipeline Blend Filter Texture");

  return Snapshot{
      .texture = out_texture,
      .transform = Matrix::MakeTranslation(coverage.origin),
      .sampler_descriptor =
          inputs[0]->GetSnapshot(renderer, entity)->sampler_descriptor};
}

#define BLEND_CASE(mode)                                                  \
  case BlendMode::k##mode:                                                \
    advanced_blend_proc_ = [](const FilterInput::Vector& inputs,          \
                              const ContentContext& renderer,             \
                              const Entity& entity, const Rect& coverage, \
                              std::optional<Color> fg_color) {            \
      PipelineProc p = &ContentContext::GetBlend##mode##Pipeline;         \
      return AdvancedBlend<BlendScreenPipeline>(inputs, renderer, entity, \
                                                coverage, fg_color, p);   \
    };                                                                    \
    break;

void BlendFilterContents::SetBlendMode(BlendMode blend_mode) {
  if (blend_mode > Entity::kLastAdvancedBlendMode) {
    VALIDATION_LOG << "Invalid blend mode " << static_cast<int>(blend_mode)
                   << " assigned to BlendFilterContents.";
  }

  blend_mode_ = blend_mode;

  if (blend_mode > Entity::kLastPipelineBlendMode) {
    switch (blend_mode) {
      BLEND_CASE(Screen)
      BLEND_CASE(Overlay)
      BLEND_CASE(Darken)
      BLEND_CASE(Lighten)
      BLEND_CASE(ColorDodge)
      BLEND_CASE(ColorBurn)
      BLEND_CASE(HardLight)
      BLEND_CASE(SoftLight)
      BLEND_CASE(Difference)
      BLEND_CASE(Exclusion)
      BLEND_CASE(Multiply)
      BLEND_CASE(Hue)
      BLEND_CASE(Saturation)
      BLEND_CASE(Color)
      BLEND_CASE(Luminosity)
      default:
        FML_UNREACHABLE();
    }
  }
}

void BlendFilterContents::SetForegroundColor(std::optional<Color> color) {
  foreground_color_ = color;
}

std::optional<Snapshot> BlendFilterContents::RenderFilter(
    const FilterInput::Vector& inputs,
    const ContentContext& renderer,
    const Entity& entity,
    const Matrix& effect_transform,
    const Rect& coverage) const {
  if (inputs.empty()) {
    return std::nullopt;
  }

  if (inputs.size() == 1 && !foreground_color_.has_value()) {
    // Nothing to blend.
    return PipelineBlend(inputs, renderer, entity, coverage, BlendMode::kSource,
                         std::nullopt);
  }

  if (blend_mode_ <= Entity::kLastPipelineBlendMode) {
    return PipelineBlend(inputs, renderer, entity, coverage, blend_mode_,
                         foreground_color_);
  }

  if (blend_mode_ <= Entity::kLastAdvancedBlendMode) {
    return advanced_blend_proc_(inputs, renderer, entity, coverage,
                                foreground_color_);
  }
  FML_UNREACHABLE();
}

}  // namespace impeller
<|endoftext|>


<commit_before>//===- CallGraph.cpp - Build a Module's call graph --------------------------=//
//
// This file implements call graph construction (from a module), and will
// eventually implement call graph serialization and deserialization for
// annotation support.
//
// This call graph represents a dynamic method invocation as a null method node.
// A call graph may only have up to one null method node that represents all of
// the dynamic method invocations.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/iOther.h"
#include "llvm/iTerminators.h"
#include "llvm/Support/InstIterator.h"// FIXME: CallGraph should use method uses
#include "Support/STLExtras.h"
#include <algorithm>

AnalysisID CallGraph::ID(AnalysisID::create<CallGraph>());
//AnalysisID CallGraph::ID(AnalysisID::template AnalysisID<CallGraph>());

// getNodeFor - Return the node for the specified method or create one if it
// does not already exist.
//
CallGraphNode *CallGraph::getNodeFor(Method *M) {
  iterator I = MethodMap.find(M);
  if (I != MethodMap.end()) return I->second;

  assert(M->getParent() == Mod && "Method not in current module!");
  CallGraphNode *New = new CallGraphNode(M);

  MethodMap.insert(std::make_pair(M, New));
  return New;
}

// addToCallGraph - Add a method to the call graph, and link the node to all of
// the methods that it calls.
//
void CallGraph::addToCallGraph(Method *M) {
  CallGraphNode *Node = getNodeFor(M);

  // If this method has external linkage,
  if (!M->hasInternalLinkage())
    Root->addCalledMethod(Node);

  for (inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I) {
    // Dynamic calls will cause Null nodes to be created
    if (CallInst *CI = dyn_cast<CallInst>(*I))
      Node->addCalledMethod(getNodeFor(CI->getCalledMethod()));
    else if (InvokeInst *II = dyn_cast<InvokeInst>(*I))
      Node->addCalledMethod(getNodeFor(II->getCalledMethod()));
  }
}

bool CallGraph::run(Module *TheModule) {
  destroy();

  Mod = TheModule;

  // Create the root node of the module...
  Root = new CallGraphNode(0);

  // Add every method to the call graph...
  for_each(Mod->begin(), Mod->end(), bind_obj(this,&CallGraph::addToCallGraph));

  return false;
}

void CallGraph::destroy() {
  for (MethodMapTy::iterator I = MethodMap.begin(), E = MethodMap.end();
       I != E; ++I) {
    delete I->second;
  }
  MethodMap.clear();
}

void WriteToOutput(const CallGraphNode *CGN, std::ostream &o) {
  if (CGN->getMethod())
    o << "Call graph node for method: '" << CGN->getMethod()->getName() <<"'\n";
  else
    o << "Call graph node null method:\n";

  for (unsigned i = 0; i < CGN->size(); ++i)
    o << "  Calls method '" << (*CGN)[i]->getMethod()->getName() << "'\n";
  o << "\n";
}

void WriteToOutput(const CallGraph &CG, std::ostream &o) {
  WriteToOutput(CG.getRoot(), o);
  for (CallGraph::const_iterator I = CG.begin(), E = CG.end(); I != E; ++I)
    o << I->second;
}

//===----------------------------------------------------------------------===//
// Implementations of public modification methods
//

// Methods to keep a call graph up to date with a method that has been
// modified
//
void CallGraph::addMethodToModule(Method *Meth) {
  assert(0 && "not implemented");
  abort();
}

// removeMethodFromModule - Unlink the method from this module, returning it.
// Because this removes the method from the module, the call graph node is
// destroyed.  This is only valid if the method does not call any other
// methods (ie, there are no edges in it's CGN).  The easiest way to do this
// is to dropAllReferences before calling this.
//
Method *CallGraph::removeMethodFromModule(CallGraphNode *CGN) {
  assert(CGN->CalledMethods.empty() && "Cannot remove method from call graph"
	 " if it references other methods!");
  Method *M = CGN->getMethod();  // Get the method for the call graph node
  delete CGN;                    // Delete the call graph node for this method
  MethodMap.erase(M);            // Remove the call graph node from the map

  Mod->getMethodList().remove(M);
  return M;
}

//
// Checks if a method contains any call instructions.
// Note that this uses the call graph only if one is provided.
// It does not build the call graph.
//
bool IsLeafMethod(const Method* M, const CallGraph* CG) {
  if (CG) {
    const CallGraphNode *cgn = (*CG)[M];
    return (cgn->begin() == cgn->end());
  }

  for (const_inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I)
    if ((*I)->getOpcode() == Instruction::Call)
      return false;
  return true;
}

<commit_msg>Move call graph printing support out of Writer.h into Callgraph.h remove dead global function<commit_after>//===- CallGraph.cpp - Build a Module's call graph ------------------------===//
//
// This file implements call graph construction (from a module), and will
// eventually implement call graph serialization and deserialization for
// annotation support.
//
// This call graph represents a dynamic method invocation as a null method node.
// A call graph may only have up to one null method node that represents all of
// the dynamic method invocations.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/CallGraph.h"
#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/iOther.h"
#include "llvm/iTerminators.h"
#include "llvm/Support/InstIterator.h"// FIXME: CallGraph should use method uses
#include "Support/STLExtras.h"
#include <algorithm>
#include <iostream>

AnalysisID CallGraph::ID(AnalysisID::create<CallGraph>());

// getNodeFor - Return the node for the specified method or create one if it
// does not already exist.
//
CallGraphNode *CallGraph::getNodeFor(Method *M) {
  iterator I = MethodMap.find(M);
  if (I != MethodMap.end()) return I->second;

  assert(M->getParent() == Mod && "Method not in current module!");
  CallGraphNode *New = new CallGraphNode(M);

  MethodMap.insert(std::make_pair(M, New));
  return New;
}

// addToCallGraph - Add a method to the call graph, and link the node to all of
// the methods that it calls.
//
void CallGraph::addToCallGraph(Method *M) {
  CallGraphNode *Node = getNodeFor(M);

  // If this method has external linkage,
  if (!M->hasInternalLinkage())
    Root->addCalledMethod(Node);

  for (inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I) {
    // Dynamic calls will cause Null nodes to be created
    if (CallInst *CI = dyn_cast<CallInst>(*I))
      Node->addCalledMethod(getNodeFor(CI->getCalledMethod()));
    else if (InvokeInst *II = dyn_cast<InvokeInst>(*I))
      Node->addCalledMethod(getNodeFor(II->getCalledMethod()));
  }
}

bool CallGraph::run(Module *TheModule) {
  destroy();

  Mod = TheModule;

  // Create the root node of the module...
  Root = new CallGraphNode(0);

  // Add every method to the call graph...
  for_each(Mod->begin(), Mod->end(), bind_obj(this,&CallGraph::addToCallGraph));

  return false;
}

void CallGraph::destroy() {
  for (MethodMapTy::iterator I = MethodMap.begin(), E = MethodMap.end();
       I != E; ++I) {
    delete I->second;
  }
  MethodMap.clear();
}

void WriteToOutput(const CallGraphNode *CGN, std::ostream &o) {
  if (CGN->getMethod())
    o << "Call graph node for method: '" << CGN->getMethod()->getName() <<"'\n";
  else
    o << "Call graph node null method:\n";

  for (unsigned i = 0; i < CGN->size(); ++i)
    o << "  Calls method '" << (*CGN)[i]->getMethod()->getName() << "'\n";
  o << "\n";
}

void WriteToOutput(const CallGraph &CG, std::ostream &o) {
  WriteToOutput(CG.getRoot(), o);
  for (CallGraph::const_iterator I = CG.begin(), E = CG.end(); I != E; ++I)
    o << I->second;
}

//===----------------------------------------------------------------------===//
// Implementations of public modification methods
//

// Methods to keep a call graph up to date with a method that has been
// modified
//
void CallGraph::addMethodToModule(Method *Meth) {
  assert(0 && "not implemented");
  abort();
}

// removeMethodFromModule - Unlink the method from this module, returning it.
// Because this removes the method from the module, the call graph node is
// destroyed.  This is only valid if the method does not call any other
// methods (ie, there are no edges in it's CGN).  The easiest way to do this
// is to dropAllReferences before calling this.
//
Method *CallGraph::removeMethodFromModule(CallGraphNode *CGN) {
  assert(CGN->CalledMethods.empty() && "Cannot remove method from call graph"
	 " if it references other methods!");
  Method *M = CGN->getMethod();  // Get the method for the call graph node
  delete CGN;                    // Delete the call graph node for this method
  MethodMap.erase(M);            // Remove the call graph node from the map

  Mod->getMethodList().remove(M);
  return M;
}

<|endoftext|>


<commit_before>/**
* Copyright (c) 2015 committers of YAKINDU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     committers of YAKINDU - initial API and implementation
*/
#include <string>
#include "gtest/gtest.h"
#include "OperationsWithoutBraces.h"
#include "OperationsWithoutBracesRequired.h"

OperationsWithoutBraces handle;

TEST(StatemachineTest, OperationsWithoutBracesTest) {
	operationsWithoutBraces_init(&handle);
	operationsWithoutBraces_enter(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_A));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_A));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_B));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_B));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_C));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_C));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_D));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_D));
}

sc_boolean operationsWithoutBracesIface_myBoolOp(OperationsWithoutBraces* handle){
	return false;
}

sc_integer operationsWithoutBracesIface_myIntOp(OperationsWithoutBraces* handle){
	return 0;
}

sc_real operationsWithoutBracesIface_myRealOp(OperationsWithoutBraces* handle){
	return 0.0;
}
<commit_msg>Added const in test data (#326).<commit_after>/**
* Copyright (c) 2015 committers of YAKINDU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     committers of YAKINDU - initial API and implementation
*/
#include <string>
#include "gtest/gtest.h"
#include "OperationsWithoutBraces.h"
#include "OperationsWithoutBracesRequired.h"

OperationsWithoutBraces handle;

TEST(StatemachineTest, OperationsWithoutBracesTest) {
	operationsWithoutBraces_init(&handle);
	operationsWithoutBraces_enter(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_A));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_A));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_B));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_B));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_C));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_C));
	operationsWithoutBraces_runCycle(&handle);
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_main_region_D));
	EXPECT_TRUE(operationsWithoutBraces_isStateActive(&handle, OperationsWithoutBraces_another_region_D));
}

sc_boolean operationsWithoutBracesIface_myBoolOp(const OperationsWithoutBraces* handle){
	return false;
}

sc_integer operationsWithoutBracesIface_myIntOp(const OperationsWithoutBraces* handle){
	return 0;
}

sc_real operationsWithoutBracesIface_myRealOp(const OperationsWithoutBraces* handle){
	return 0.0;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// FILE:          Standa.cpp
// PROJECT:       Micro-Manager
// SUBSYSTEM:     DeviceAdapters
//-----------------------------------------------------------------------------
// DESCRIPTION:   Standa device adapters: 8SMC1-USBhF Microstep Driver
//
// COPYRIGHT:     Leslie Lab, McGill University, Montreal, 2013
//
// LICENSE:       This file is distributed under the BSD license.
//
//                This file is distributed in the hope that it will be useful,
//                but WITHOUT ANY WARRANTY; without even the implied warranty
//                of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//                IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//                CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//                INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.
//
// AUTHOR:        Clarence Leung, clarence.leung@mail.mcgill.ca, 2013
//

#ifdef WIN32
   #include <windows.h>
   #define snprintf _snprintf
#endif

#include "Standa.h"

const char* StandaZStage::DeviceName_ = "StandaZStage";
const char* g_Standa_ZStageAxisLimitUm = "Limit_um";
const char* g_Standa_ZStageDeviceNumber = "Device Number";

USMC_Devices deviceList;

///////////////////////////////////////////////////////////////////////////////
// Exported MMDevice API
///////////////////////////////////////////////////////////////////////////////
MODULE_API void InitializeModuleData()
{
   AddAvailableDeviceName(StandaZStage::DeviceName_, "Standa Z Stage");
}

MODULE_API MM::Device* CreateDevice(const char* deviceName)
{
   if (deviceName == 0)
   {
      return 0;
   }

   if (strcmp(deviceName, StandaZStage::DeviceName_) == 0)
   {
      StandaZStage* s = new StandaZStage();
      return s;
   }

   return 0;
}

MODULE_API void DeleteDevice(MM::Device* pDevice)
{
   delete pDevice;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// ZStage

StandaZStage::StandaZStage() :
   initialized_(false),
   stepSizeUm_(0.001),
   axisLimitUm_(500.0),
   stepDivisor_(8),
   stageSpeed_(2000.0),
   timeOutTimer_(0),
   deviceString_(""),
   deviceNumber_(0)
{
   InitializeDefaultErrorMessages();

   // create pre-initialization properties
   // ------------------------------------

   // Name
   CreateProperty(MM::g_Keyword_Name, StandaZStage::DeviceName_, MM::String, true);

   // Description
   CreateProperty(MM::g_Keyword_Description, "Standa Z-stage driver adapter", MM::String, true);

   CPropertyAction* pAct;

   // Device Number
   pAct = new CPropertyAction (this, &StandaZStage::OnDeviceNumber);
   CreateProperty(g_Standa_ZStageDeviceNumber, "Undefined", MM::String, false, pAct, true);

   // Axis Limit in um
   pAct = new CPropertyAction (this, &StandaZStage::OnAxisLimit);
   CreateProperty(g_Standa_ZStageAxisLimitUm, "500.0", MM::Float, false, pAct, true);

   // Axis limits (assumed symmetrical)
   pAct = new CPropertyAction (this, &StandaZStage::OnPosition);
   CreateProperty(MM::g_Keyword_Position, "0.0", MM::Float, false, pAct);
   SetPropertyLimits(MM::g_Keyword_Position, 0, axisLimitUm_);
}

StandaZStage::~StandaZStage()
{
   Shutdown();
}

void StandaZStage::GetName(char* Name) const
{
   CDeviceUtils::CopyLimitedString(Name, StandaZStage::DeviceName_);
}

bool StandaZStage::Busy()
{
   if (timeOutTimer_ == 0)
   {
      return false;
   }

   if (timeOutTimer_->expired(GetCurrentMMTime()))
   {
      return false;
   }

   return true;
}

int StandaZStage::Initialize()
{
   // Initialize the list of devices to search for the stage
   if (USMC_Init(deviceList))
   {
      return DEVICE_ERR;
   }

   // Parse the device number from the user-entered string
   deviceNumber_ = atoi(deviceString_.c_str());

   // Attempt to get the current state of the device
   if (USMC_GetState(deviceNumber_, currentState_))
   {
      return DEVICE_ERR;
   }

   // Attempt to get the current position, in steps
   int ret = GetPositionSteps(curSteps_);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   initialized_ = true;
   return DEVICE_OK;
}

int StandaZStage::Shutdown()
{
   if (initialized_)
   {
      initialized_ = false;
   }

   return DEVICE_OK;
}

int StandaZStage::GetPositionUm(double &pos)
{
   long steps;
   int ret = GetPositionSteps(steps);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   pos = steps * stepSizeUm_;
   return DEVICE_OK;
}

int StandaZStage::SetPositionUm(double pos)
{
   long steps = (long) (pos / stepSizeUm_ + 0.5);
   int ret = SetPositionSteps(steps);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   return OnStagePositionChanged(pos);
}

int StandaZStage::GetPositionSteps(long& steps) {
   // Note that steps on the Standa stage refer to micro-steps,
   // which are one-eighth of a full step.
   if (USMC_GetState(deviceNumber_, currentState_))
   {
      return DEVICE_ERR;
   }

   steps = (long) currentState_.CurPos;

   return DEVICE_OK;
}

int StandaZStage::SetPositionSteps(long steps)
{
   // Get the initial starting parameters
   if (USMC_GetStartParameters(deviceNumber_, startParameters_))
   {
      return DEVICE_ERR;
   }

   // Set the step divisor to our desired step divisor
   startParameters_.SDivisor = stepDivisor_;

   // Start the movement of the stepper motor
   if (USMC_Start(deviceNumber_, (int) steps, stageSpeed_, startParameters_))
   {
      return DEVICE_ERR;
   }

   return DEVICE_OK;
}

int StandaZStage::SetOrigin()
{
   return DEVICE_UNSUPPORTED_COMMAND;
}

int StandaZStage::GetLimits(double& min, double& max)
{
   min = 0;
   max = axisLimitUm_;
   return DEVICE_OK;
}

///////////////////////////////////////////////////////////////////////////////
// Action handlers
///////////////////////////////////////////////////////////////////////////////

int StandaZStage::OnAxisLimit(MM::PropertyBase *pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      pProp->Set(axisLimitUm_);
      SetPropertyLimits(MM::g_Keyword_Position, 0, axisLimitUm_);
   }
   else if (eAct == MM::AfterSet)
   {
      pProp->Get(axisLimitUm_);
   }

   return DEVICE_OK;
}

int StandaZStage::OnDeviceNumber(MM::PropertyBase *pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      pProp->Set(deviceString_.c_str());
   }
   else if (eAct == MM::AfterSet)
   {
      pProp->Get(deviceString_);
   }

   return DEVICE_OK;
}

int StandaZStage::OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      if (!initialized_)
      {
         pProp->Set(0.0);
         return DEVICE_OK;
      }
      double pos;
      int ret = GetPositionUm(pos);
      if (ret != DEVICE_OK)
      {
         return ret;
      }

      pProp->Set(pos);
   }
   else if (eAct == MM::AfterSet)
   {
       if (!initialized_)
      {
         return DEVICE_OK;
      }
     double pos;
      pProp->Get(pos);
      int ret = SetPositionUm(pos);
      if (ret != DEVICE_OK)
      {
         return ret;
      }
   }

   return DEVICE_OK;
}<commit_msg>Standa: Make global variable local to module.<commit_after>///////////////////////////////////////////////////////////////////////////////
// FILE:          Standa.cpp
// PROJECT:       Micro-Manager
// SUBSYSTEM:     DeviceAdapters
//-----------------------------------------------------------------------------
// DESCRIPTION:   Standa device adapters: 8SMC1-USBhF Microstep Driver
//
// COPYRIGHT:     Leslie Lab, McGill University, Montreal, 2013
//
// LICENSE:       This file is distributed under the BSD license.
//
//                This file is distributed in the hope that it will be useful,
//                but WITHOUT ANY WARRANTY; without even the implied warranty
//                of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//                IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//                CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//                INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.
//
// AUTHOR:        Clarence Leung, clarence.leung@mail.mcgill.ca, 2013
//

#ifdef WIN32
   #include <windows.h>
   #define snprintf _snprintf
#endif

#include "Standa.h"

const char* StandaZStage::DeviceName_ = "StandaZStage";
const char* g_Standa_ZStageAxisLimitUm = "Limit_um";
const char* g_Standa_ZStageDeviceNumber = "Device Number";

static USMC_Devices deviceList;

///////////////////////////////////////////////////////////////////////////////
// Exported MMDevice API
///////////////////////////////////////////////////////////////////////////////
MODULE_API void InitializeModuleData()
{
   AddAvailableDeviceName(StandaZStage::DeviceName_, "Standa Z Stage");
}

MODULE_API MM::Device* CreateDevice(const char* deviceName)
{
   if (deviceName == 0)
   {
      return 0;
   }

   if (strcmp(deviceName, StandaZStage::DeviceName_) == 0)
   {
      StandaZStage* s = new StandaZStage();
      return s;
   }

   return 0;
}

MODULE_API void DeleteDevice(MM::Device* pDevice)
{
   delete pDevice;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// ZStage

StandaZStage::StandaZStage() :
   initialized_(false),
   stepSizeUm_(0.001),
   axisLimitUm_(500.0),
   stepDivisor_(8),
   stageSpeed_(2000.0),
   timeOutTimer_(0),
   deviceString_(""),
   deviceNumber_(0)
{
   InitializeDefaultErrorMessages();

   // create pre-initialization properties
   // ------------------------------------

   // Name
   CreateProperty(MM::g_Keyword_Name, StandaZStage::DeviceName_, MM::String, true);

   // Description
   CreateProperty(MM::g_Keyword_Description, "Standa Z-stage driver adapter", MM::String, true);

   CPropertyAction* pAct;

   // Device Number
   pAct = new CPropertyAction (this, &StandaZStage::OnDeviceNumber);
   CreateProperty(g_Standa_ZStageDeviceNumber, "Undefined", MM::String, false, pAct, true);

   // Axis Limit in um
   pAct = new CPropertyAction (this, &StandaZStage::OnAxisLimit);
   CreateProperty(g_Standa_ZStageAxisLimitUm, "500.0", MM::Float, false, pAct, true);

   // Axis limits (assumed symmetrical)
   pAct = new CPropertyAction (this, &StandaZStage::OnPosition);
   CreateProperty(MM::g_Keyword_Position, "0.0", MM::Float, false, pAct);
   SetPropertyLimits(MM::g_Keyword_Position, 0, axisLimitUm_);
}

StandaZStage::~StandaZStage()
{
   Shutdown();
}

void StandaZStage::GetName(char* Name) const
{
   CDeviceUtils::CopyLimitedString(Name, StandaZStage::DeviceName_);
}

bool StandaZStage::Busy()
{
   if (timeOutTimer_ == 0)
   {
      return false;
   }

   if (timeOutTimer_->expired(GetCurrentMMTime()))
   {
      return false;
   }

   return true;
}

int StandaZStage::Initialize()
{
   // Initialize the list of devices to search for the stage
   if (USMC_Init(deviceList))
   {
      return DEVICE_ERR;
   }

   // Parse the device number from the user-entered string
   deviceNumber_ = atoi(deviceString_.c_str());

   // Attempt to get the current state of the device
   if (USMC_GetState(deviceNumber_, currentState_))
   {
      return DEVICE_ERR;
   }

   // Attempt to get the current position, in steps
   int ret = GetPositionSteps(curSteps_);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   initialized_ = true;
   return DEVICE_OK;
}

int StandaZStage::Shutdown()
{
   if (initialized_)
   {
      initialized_ = false;
   }

   return DEVICE_OK;
}

int StandaZStage::GetPositionUm(double &pos)
{
   long steps;
   int ret = GetPositionSteps(steps);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   pos = steps * stepSizeUm_;
   return DEVICE_OK;
}

int StandaZStage::SetPositionUm(double pos)
{
   long steps = (long) (pos / stepSizeUm_ + 0.5);
   int ret = SetPositionSteps(steps);

   if (ret != DEVICE_OK)
   {
      return ret;
   }

   return OnStagePositionChanged(pos);
}

int StandaZStage::GetPositionSteps(long& steps) {
   // Note that steps on the Standa stage refer to micro-steps,
   // which are one-eighth of a full step.
   if (USMC_GetState(deviceNumber_, currentState_))
   {
      return DEVICE_ERR;
   }

   steps = (long) currentState_.CurPos;

   return DEVICE_OK;
}

int StandaZStage::SetPositionSteps(long steps)
{
   // Get the initial starting parameters
   if (USMC_GetStartParameters(deviceNumber_, startParameters_))
   {
      return DEVICE_ERR;
   }

   // Set the step divisor to our desired step divisor
   startParameters_.SDivisor = stepDivisor_;

   // Start the movement of the stepper motor
   if (USMC_Start(deviceNumber_, (int) steps, stageSpeed_, startParameters_))
   {
      return DEVICE_ERR;
   }

   return DEVICE_OK;
}

int StandaZStage::SetOrigin()
{
   return DEVICE_UNSUPPORTED_COMMAND;
}

int StandaZStage::GetLimits(double& min, double& max)
{
   min = 0;
   max = axisLimitUm_;
   return DEVICE_OK;
}

///////////////////////////////////////////////////////////////////////////////
// Action handlers
///////////////////////////////////////////////////////////////////////////////

int StandaZStage::OnAxisLimit(MM::PropertyBase *pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      pProp->Set(axisLimitUm_);
      SetPropertyLimits(MM::g_Keyword_Position, 0, axisLimitUm_);
   }
   else if (eAct == MM::AfterSet)
   {
      pProp->Get(axisLimitUm_);
   }

   return DEVICE_OK;
}

int StandaZStage::OnDeviceNumber(MM::PropertyBase *pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      pProp->Set(deviceString_.c_str());
   }
   else if (eAct == MM::AfterSet)
   {
      pProp->Get(deviceString_);
   }

   return DEVICE_OK;
}

int StandaZStage::OnPosition(MM::PropertyBase* pProp, MM::ActionType eAct)
{
   if (eAct == MM::BeforeGet)
   {
      if (!initialized_)
      {
         pProp->Set(0.0);
         return DEVICE_OK;
      }
      double pos;
      int ret = GetPositionUm(pos);
      if (ret != DEVICE_OK)
      {
         return ret;
      }

      pProp->Set(pos);
   }
   else if (eAct == MM::AfterSet)
   {
       if (!initialized_)
      {
         return DEVICE_OK;
      }
     double pos;
      pProp->Get(pos);
      int ret = SetPositionUm(pos);
      if (ret != DEVICE_OK)
      {
         return ret;
      }
   }

   return DEVICE_OK;
}<|endoftext|>