<commit_before>/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

#include <string.h>
#include <initializer_list>

namespace skiagm {

namespace {
const SkScalar kTextSizes[] = {12, 18, 30, 120};
const char kTestFontName[] = "fonts/test_glyphs-glyf_colr_1.ttf";
const char kTestFontNameVariable[] = "fonts/test_glyphs-glyf_colr_1_variable.ttf";
const SkScalar xWidth = 1200;
const SkScalar xTranslate = 200;
}

class ColrV1GM : public GM {
public:
    ColrV1GM(const char* testName,
             SkSpan<const uint32_t> codepoints,
             SkScalar skewX,
             SkScalar rotateDeg,
             std::initializer_list<SkFontArguments::VariationPosition::Coordinate>
                     specifiedVariations)
            : fTestName(testName)
            , fCodepoints(codepoints)
            , fSkewX(skewX)
            , fRotateDeg(rotateDeg) {
        fVariationPosition.coordinateCount = specifiedVariations.size();
        fCoordinates = std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>(
                specifiedVariations.size());
        for (size_t i = 0; i < specifiedVariations.size(); ++i) {
            fCoordinates[i] = std::data(specifiedVariations)[i];
        }

        fVariationPosition.coordinates = fCoordinates.get();
    }

protected:
    void onOnceBeforeDraw() override {
        if (fVariationPosition.coordinateCount) {
            fTypeface = MakeResourceAsTypeface(kTestFontNameVariable);
        } else {
            fTypeface = MakeResourceAsTypeface(kTestFontName);
        }
        fVariationSliders = ToolUtils::VariationSliders(fTypeface.get(), fVariationPosition);
    }

    SkString onShortName() override {
        SkASSERT(!fTestName.isEmpty());
        SkString gm_name = SkStringPrintf("colrv1_%s", fTestName.c_str());

        if (fSkewX) {
            gm_name.append(SkStringPrintf("_skew_%.2f", fSkewX));
        }

        if (fRotateDeg) {
            gm_name.append(SkStringPrintf("_rotate_%.2f", fRotateDeg));
        }

        for (int i = 0; i < fVariationPosition.coordinateCount; ++i) {
            SkString tagName = ToolUtils::VariationSliders::tagToString(
                    fVariationPosition.coordinates[i].axis);
            gm_name.append(SkStringPrintf(
                    "_%s_%.2f", tagName.c_str(), fVariationPosition.coordinates[i].value));
        }

        return gm_name;
    }

    bool onGetControls(SkMetaData* controls) override {
        return fVariationSliders.writeControls(controls);
    }

    void onSetControls(const SkMetaData& controls) override {
        return fVariationSliders.readControls(controls);
    }

    SkISize onISize() override {
        return SkISize::Make(xWidth, xWidth);
    }

    sk_sp<SkTypeface> makeVariedTypeface() {
        if (!fTypeface) {
            return nullptr;
        }
        SkSpan<const SkFontArguments::VariationPosition::Coordinate> coords =
                fVariationSliders.getCoordinates();
        SkFontArguments::VariationPosition varPos = {coords.data(),
                                                     static_cast<int>(coords.size())};
        SkFontArguments args;
        args.setVariationDesignPosition(varPos);
        return fTypeface->makeClone(args);
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        canvas->drawColor(SK_ColorWHITE);
        SkPaint paint;

        canvas->translate(xTranslate, 20);

        if (!fTypeface) {
          *errorMsg = "Did not recognize COLR v1 font format.";
          return DrawResult::kSkip;
        }

        canvas->rotate(fRotateDeg);
        canvas->skew(fSkewX, 0);

        SkFont font(makeVariedTypeface());

        SkFontMetrics metrics;
        SkScalar y = 0;
        std::vector<SkColor> paint_colors = {
                SK_ColorBLACK, SK_ColorGREEN, SK_ColorRED, SK_ColorBLUE};
        auto paint_color_iterator = paint_colors.begin();
        for (SkScalar textSize : kTextSizes) {
            font.setSize(textSize);
            font.getMetrics(&metrics);
            SkScalar y_shift = -(metrics.fAscent + metrics.fDescent + metrics.fLeading) * 1.2;
            y += y_shift;
            paint.setColor(*paint_color_iterator);
            int x = 0;
            // Perform simple line breaking to fit more glyphs into the GM canvas.
            for (size_t i = 0; i < fCodepoints.size(); ++i) {
                canvas->drawSimpleText(&fCodepoints[i],
                                       sizeof(uint32_t),
                                       SkTextEncoding::kUTF32,
                                       x,
                                       y,
                                       font,
                                       paint);
                SkScalar glyphAdvance = font.measureText(
                        &fCodepoints[i], sizeof(uint32_t), SkTextEncoding::kUTF32, nullptr);
                if (x + glyphAdvance < xWidth - xTranslate) {
                    x += glyphAdvance + glyphAdvance * 0.05f;
                } else {
                    y += y_shift;
                    x = 0;
                }
            }
            paint_color_iterator++;
        }
        return DrawResult::kOk;
    }

private:
    using INHERITED = GM;

    SkString fTestName;
    sk_sp<SkTypeface> fTypeface;
    SkSpan<const uint32_t> fCodepoints;
    SkScalar fSkewX;
    SkScalar fRotateDeg;
    std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoordinates;
    SkFontArguments::VariationPosition fVariationPosition;
    ToolUtils::VariationSliders fVariationSliders;
};

// Generated using test glyphs generator script from https://github.com/googlefonts/color-fonts:
// $ python3 config/test_glyphs-glyf_colr_1.py -vvv  --generate-descriptions fonts/
// Regenerate descriptions and paste the generated arrays here when updating the test font.
namespace ColrV1TestDefinitions {
const uint32_t gradient_stops_repeat[] = {0xf0100, 0xf0101, 0xf0102, 0xf0103};
const uint32_t sweep_varsweep[] = {0xf0200, 0xf0201, 0xf0202, 0xf0203, 0xf0204, 0xf0205,
                                   0xf0206, 0xf0207, 0xf0208, 0xf0209, 0xf020a, 0xf020b,
                                   0xf020c, 0xf020d, 0xf020e, 0xf020f, 0xf0210, 0xf0211,
                                   0xf0212, 0xf0213, 0xf0214, 0xf0215, 0xf0216, 0xf0217};
const uint32_t paint_scale[] = {0xf0300, 0xf0301, 0xf0302, 0xf0303, 0xf0304, 0xf0305};
const uint32_t extend_mode[] = {0xf0500, 0xf0501, 0xf0502, 0xf0503, 0xf0504, 0xf0505};
const uint32_t paint_rotate[] = {0xf0600, 0xf0601, 0xf0602, 0xf0603};
const uint32_t paint_skew[] = {0xf0700, 0xf0701, 0xf0702, 0xf0703, 0xf0704, 0xf0705};
const uint32_t paint_transform[] = {0xf0800, 0xf0801, 0xf0802, 0xf0803};
const uint32_t paint_translate[] = {0xf0900, 0xf0901, 0xf0902, 0xf0903, 0xf0904, 0xf0905, 0xf0906};
const uint32_t composite_mode[] = {0xf0a00, 0xf0a01, 0xf0a02, 0xf0a03, 0xf0a04, 0xf0a05, 0xf0a06,
                                   0xf0a07, 0xf0a08, 0xf0a09, 0xf0a0a, 0xf0a0b, 0xf0a0c, 0xf0a0d,
                                   0xf0a0e, 0xf0a0f, 0xf0a10, 0xf0a11, 0xf0a12, 0xf0a13, 0xf0a14,
                                   0xf0a15, 0xf0a16, 0xf0a17, 0xf0a18, 0xf0a19, 0xf0a1a, 0xf0a1b};
const uint32_t foreground_color[] = {
        0xf0b00, 0xf0b01, 0xf0b02, 0xf0b03, 0xf0b04, 0xf0b05, 0xf0b06, 0xf0b07};
const uint32_t clipbox[] = {0xf0c00, 0xf0c01, 0xf0c02, 0xf0c03, 0xf0c04};
const uint32_t gradient_p2_skewed[] = {0xf0d00};
const uint32_t variable_alpha[] = {0xf1000};
};  // namespace ColrV1TestDefinitions

namespace {
std::unique_ptr<ColrV1GM> F(
    const char* name,
    SkSpan<const uint32_t> codepoints,
    SkScalar skewX,
    SkScalar rotateDeg,
    std::initializer_list<SkFontArguments::VariationPosition::Coordinate> variations)
{
    return std::make_unique<ColrV1GM>(name, codepoints, skewX, rotateDeg, variations);
}

SkFourByteTag constexpr operator "" _t(const char* tagName, size_t size) {
    SkASSERT(size == 4);
    return SkSetFourByteTag(tagName[0], tagName[1], tagName[2], tagName[3]);
}
}
#define C(TEST_CATEGORY) #TEST_CATEGORY, ColrV1TestDefinitions::TEST_CATEGORY
DEF_GM(return F(C(clipbox),                0.0f,  0.0f, {}))
DEF_GM(return F(C(clipbox),                0.0f,  0.0f, {{"CLIO"_t, 200}}))
DEF_GM(return F(C(composite_mode),         0.0f,  0.0f, {}))
DEF_GM(return F(C(composite_mode),        -0.5f,  0.0f, {}))
DEF_GM(return F(C(composite_mode),        -0.5f, 20.0f, {}))
DEF_GM(return F(C(composite_mode),         0.0f, 20.0f, {}))
DEF_GM(return F(C(extend_mode),            0.0f,  0.0f, {}))
DEF_GM(return F(C(extend_mode),           -0.5f,  0.0f, {}))
DEF_GM(return F(C(extend_mode),           -0.5f, 20.0f, {}))
DEF_GM(return F(C(extend_mode),            0.0f, 20.0f, {}))
DEF_GM(return F(C(foreground_color),       0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_p2_skewed),     0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat),  0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat), -0.5f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat), -0.5f, 20.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat),  0.0f, 20.0f, {}))
DEF_GM(return F(C(paint_rotate),           0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_skew),             0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_transform),        0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_translate),        0.0f,  0.0f, {}))
DEF_GM(return F(C(sweep_varsweep),         0.0f,  0.0f, {}))
DEF_GM(return F(C(sweep_varsweep),        -0.5f,  0.0f, {}))
DEF_GM(return F(C(sweep_varsweep),        -0.5f, 20.0f, {}))
DEF_GM(return F(C(sweep_varsweep),         0.0f, 20.0f, {}))
DEF_GM(return F(C(variable_alpha),         0.0f,  0.0f, {}))

}  // namespace skiagm
<commit_msg>Define a set of variable COLRv1 variations tests<commit_after>/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

#include <string.h>
#include <initializer_list>

namespace skiagm {

namespace {
const SkScalar kTextSizes[] = {12, 18, 30, 120};
const char kTestFontName[] = "fonts/test_glyphs-glyf_colr_1.ttf";
const char kTestFontNameVariable[] = "fonts/test_glyphs-glyf_colr_1_variable.ttf";
const SkScalar xWidth = 1200;
const SkScalar xTranslate = 200;
}

class ColrV1GM : public GM {
public:
    ColrV1GM(const char* testName,
             SkSpan<const uint32_t> codepoints,
             SkScalar skewX,
             SkScalar rotateDeg,
             std::initializer_list<SkFontArguments::VariationPosition::Coordinate>
                     specifiedVariations)
            : fTestName(testName)
            , fCodepoints(codepoints)
            , fSkewX(skewX)
            , fRotateDeg(rotateDeg) {
        fVariationPosition.coordinateCount = specifiedVariations.size();
        fCoordinates = std::make_unique<SkFontArguments::VariationPosition::Coordinate[]>(
                specifiedVariations.size());
        for (size_t i = 0; i < specifiedVariations.size(); ++i) {
            fCoordinates[i] = std::data(specifiedVariations)[i];
        }

        fVariationPosition.coordinates = fCoordinates.get();
    }

protected:
    void onOnceBeforeDraw() override {
        if (fVariationPosition.coordinateCount) {
            fTypeface = MakeResourceAsTypeface(kTestFontNameVariable);
        } else {
            fTypeface = MakeResourceAsTypeface(kTestFontName);
        }
        fVariationSliders = ToolUtils::VariationSliders(fTypeface.get(), fVariationPosition);
    }

    SkString onShortName() override {
        SkASSERT(!fTestName.isEmpty());
        SkString gm_name = SkStringPrintf("colrv1_%s", fTestName.c_str());

        if (fSkewX) {
            gm_name.append(SkStringPrintf("_skew_%.2f", fSkewX));
        }

        if (fRotateDeg) {
            gm_name.append(SkStringPrintf("_rotate_%.2f", fRotateDeg));
        }

        for (int i = 0; i < fVariationPosition.coordinateCount; ++i) {
            SkString tagName = ToolUtils::VariationSliders::tagToString(
                    fVariationPosition.coordinates[i].axis);
            gm_name.append(SkStringPrintf(
                    "_%s_%.2f", tagName.c_str(), fVariationPosition.coordinates[i].value));
        }

        return gm_name;
    }

    bool onGetControls(SkMetaData* controls) override {
        return fVariationSliders.writeControls(controls);
    }

    void onSetControls(const SkMetaData& controls) override {
        return fVariationSliders.readControls(controls);
    }

    SkISize onISize() override {
        return SkISize::Make(xWidth, xWidth);
    }

    sk_sp<SkTypeface> makeVariedTypeface() {
        if (!fTypeface) {
            return nullptr;
        }
        SkSpan<const SkFontArguments::VariationPosition::Coordinate> coords =
                fVariationSliders.getCoordinates();
        SkFontArguments::VariationPosition varPos = {coords.data(),
                                                     static_cast<int>(coords.size())};
        SkFontArguments args;
        args.setVariationDesignPosition(varPos);
        return fTypeface->makeClone(args);
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        canvas->drawColor(SK_ColorWHITE);
        SkPaint paint;

        canvas->translate(xTranslate, 20);

        if (!fTypeface) {
          *errorMsg = "Did not recognize COLR v1 font format.";
          return DrawResult::kSkip;
        }

        canvas->rotate(fRotateDeg);
        canvas->skew(fSkewX, 0);

        SkFont font(makeVariedTypeface());

        SkFontMetrics metrics;
        SkScalar y = 0;
        std::vector<SkColor> paint_colors = {
                SK_ColorBLACK, SK_ColorGREEN, SK_ColorRED, SK_ColorBLUE};
        auto paint_color_iterator = paint_colors.begin();
        for (SkScalar textSize : kTextSizes) {
            font.setSize(textSize);
            font.getMetrics(&metrics);
            SkScalar y_shift = -(metrics.fAscent + metrics.fDescent + metrics.fLeading) * 1.2;
            y += y_shift;
            paint.setColor(*paint_color_iterator);
            int x = 0;
            // Perform simple line breaking to fit more glyphs into the GM canvas.
            for (size_t i = 0; i < fCodepoints.size(); ++i) {
                canvas->drawSimpleText(&fCodepoints[i],
                                       sizeof(uint32_t),
                                       SkTextEncoding::kUTF32,
                                       x,
                                       y,
                                       font,
                                       paint);
                SkScalar glyphAdvance = font.measureText(
                        &fCodepoints[i], sizeof(uint32_t), SkTextEncoding::kUTF32, nullptr);
                if (x + glyphAdvance < xWidth - xTranslate) {
                    x += glyphAdvance + glyphAdvance * 0.05f;
                } else {
                    y += y_shift;
                    x = 0;
                }
            }
            paint_color_iterator++;
        }
        return DrawResult::kOk;
    }

private:
    using INHERITED = GM;

    SkString fTestName;
    sk_sp<SkTypeface> fTypeface;
    SkSpan<const uint32_t> fCodepoints;
    SkScalar fSkewX;
    SkScalar fRotateDeg;
    std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoordinates;
    SkFontArguments::VariationPosition fVariationPosition;
    ToolUtils::VariationSliders fVariationSliders;
};

// Generated using test glyphs generator script from https://github.com/googlefonts/color-fonts:
// $ python3 config/test_glyphs-glyf_colr_1.py -vvv  --generate-descriptions fonts/
// Regenerate descriptions and paste the generated arrays here when updating the test font.
namespace ColrV1TestDefinitions {
const uint32_t gradient_stops_repeat[] = {0xf0100, 0xf0101, 0xf0102, 0xf0103};
const uint32_t sweep_varsweep[] = {0xf0200, 0xf0201, 0xf0202, 0xf0203, 0xf0204, 0xf0205,
                                   0xf0206, 0xf0207, 0xf0208, 0xf0209, 0xf020a, 0xf020b,
                                   0xf020c, 0xf020d, 0xf020e, 0xf020f, 0xf0210, 0xf0211,
                                   0xf0212, 0xf0213, 0xf0214, 0xf0215, 0xf0216, 0xf0217};
const uint32_t paint_scale[] = {0xf0300, 0xf0301, 0xf0302, 0xf0303, 0xf0304, 0xf0305};
const uint32_t extend_mode[] = {0xf0500, 0xf0501, 0xf0502, 0xf0503, 0xf0504, 0xf0505};
const uint32_t paint_rotate[] = {0xf0600, 0xf0601, 0xf0602, 0xf0603};
const uint32_t paint_skew[] = {0xf0700, 0xf0701, 0xf0702, 0xf0703, 0xf0704, 0xf0705};
const uint32_t paint_transform[] = {0xf0800, 0xf0801, 0xf0802, 0xf0803};
const uint32_t paint_translate[] = {0xf0900, 0xf0901, 0xf0902, 0xf0903, 0xf0904, 0xf0905, 0xf0906};
const uint32_t composite_mode[] = {0xf0a00, 0xf0a01, 0xf0a02, 0xf0a03, 0xf0a04, 0xf0a05, 0xf0a06,
                                   0xf0a07, 0xf0a08, 0xf0a09, 0xf0a0a, 0xf0a0b, 0xf0a0c, 0xf0a0d,
                                   0xf0a0e, 0xf0a0f, 0xf0a10, 0xf0a11, 0xf0a12, 0xf0a13, 0xf0a14,
                                   0xf0a15, 0xf0a16, 0xf0a17, 0xf0a18, 0xf0a19, 0xf0a1a, 0xf0a1b};
const uint32_t foreground_color[] = {
        0xf0b00, 0xf0b01, 0xf0b02, 0xf0b03, 0xf0b04, 0xf0b05, 0xf0b06, 0xf0b07};
const uint32_t clipbox[] = {0xf0c00, 0xf0c01, 0xf0c02, 0xf0c03, 0xf0c04};
const uint32_t gradient_p2_skewed[] = {0xf0d00};
const uint32_t variable_alpha[] = {0xf1000};
};  // namespace ColrV1TestDefinitions

namespace {
std::unique_ptr<ColrV1GM> F(
    const char* name,
    SkSpan<const uint32_t> codepoints,
    SkScalar skewX,
    SkScalar rotateDeg,
    std::initializer_list<SkFontArguments::VariationPosition::Coordinate> variations)
{
    return std::make_unique<ColrV1GM>(name, codepoints, skewX, rotateDeg, variations);
}

SkFourByteTag constexpr operator "" _t(const char* tagName, size_t size) {
    SkASSERT(size == 4);
    return SkSetFourByteTag(tagName[0], tagName[1], tagName[2], tagName[3]);
}
}
#define C(TEST_CATEGORY) #TEST_CATEGORY, ColrV1TestDefinitions::TEST_CATEGORY
DEF_GM(return F(C(clipbox),                0.0f,  0.0f, {}))
DEF_GM(return F(C(clipbox),                0.0f,  0.0f, {{"CLIO"_t, 200.f}}))
DEF_GM(return F(C(composite_mode),         0.0f,  0.0f, {}))
DEF_GM(return F(C(composite_mode),        -0.5f,  0.0f, {}))
DEF_GM(return F(C(composite_mode),        -0.5f, 20.0f, {}))
DEF_GM(return F(C(composite_mode),         0.0f, 20.0f, {}))
DEF_GM(return F(C(extend_mode),            0.0f,  0.0f, {}))
DEF_GM(return F(C(extend_mode),           -0.5f,  0.0f, {}))
DEF_GM(return F(C(extend_mode),           -0.5f, 20.0f, {}))
DEF_GM(return F(C(extend_mode),            0.0f, 20.0f, {}))
DEF_GM(return F(C(extend_mode),            0.0f,  0.0f, {{"COL2"_t, -0.3f}}))
DEF_GM(return F(C(extend_mode),            0.0f,  0.0f, {{"GRR0"_t, 430.f}, {"GRR1"_t, 40.f}}))
DEF_GM(return F(C(foreground_color),       0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_p2_skewed),     0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat),  0.0f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat), -0.5f,  0.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat), -0.5f, 20.0f, {}))
DEF_GM(return F(C(gradient_stops_repeat),  0.0f, 20.0f, {}))
DEF_GM(return F(C(paint_rotate),           0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_rotate),           0.0f,  0.0f, {{"ROTA"_t, 40.f}}))
DEF_GM(return F(C(paint_rotate),           0.0f,  0.0f, {{"ROTX"_t, -250.f}, {"ROTY"_t, -250.f}}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {{"SCOX"_t, 200.f}, {"SCOY"_t, 200.f}}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {{"SCSX"_t, 0.25f}, {"SCOY"_t, 0.25f}}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {{"SCSX"_t, -1.f}, {"SCOY"_t, -1.f}}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_scale),            0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_skew),             0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_skew),             0.0f,  0.0f, {{"SKXA"_t, 20.f}}))
DEF_GM(return F(C(paint_skew),             0.0f,  0.0f, {{"SKYA"_t, 20.f}}))
DEF_GM(return F(C(paint_skew),             0.0f,  0.0f, {{"SKCX"_t, 200.f},{"SKCY"_t, 200.f}}))
DEF_GM(return F(C(paint_transform),        0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_translate),        0.0f,  0.0f, {}))
DEF_GM(return F(C(paint_translate),        0.0f,  0.0f, {{"TLDX"_t, 100.f}, {"TLDY"_t, 100.f}}))
DEF_GM(return F(C(sweep_varsweep),         0.0f,  0.0f, {}))
DEF_GM(return F(C(sweep_varsweep),        -0.5f,  0.0f, {}))
DEF_GM(return F(C(sweep_varsweep),        -0.5f, 20.0f, {}))
DEF_GM(return F(C(sweep_varsweep),         0.0f, 20.0f, {}))
DEF_GM(return F(C(variable_alpha),         0.0f,  0.0f, {}))
DEF_GM(return F(C(variable_alpha),         0.0f,  0.0f, {{"APH1"_t, -0.7f}}))
DEF_GM(return F(C(variable_alpha),         0.0f,  0.0f, {{"APH2"_t, -0.7f}, {"APH3"_t, -0.2f}}))

}  // namespace skiagm
<|endoftext|>


<commit_before>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/math/CMathEnum.cpp,v $
//   $Revision: 1.1 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2011/05/24 16:32:31 $
// End CVS Header

// Copyright (C) 2011 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include "copasi.h"

#include "CMathEnum.h"

CMath::CVariableStack::CVariableStack():
    mpStack(NULL),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CVariableStack::CVariableStack(CMath::CVariableStack::Buffer & stack):
    mpStack(&stack),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CVariableStack::CVariableStack(const CMath::CVariableStack & src):
    mpStack(src.mpStack),
    mContext(src.mContext),
    mVariableLevel(src.mVariableLevel),
    mBodyLevel(src.mBodyLevel)
{}

CMath::CVariableStack::~CVariableStack()
{}

void CMath::CVariableStack::push(const CMath::CVariableStack::StackElement & stackElement)
{
  mpStack->push_back(stackElement);
  mBodyLevel++;
}

void CMath::CVariableStack::pop()
{
  mpStack->pop_back();
  mBodyLevel--;
}

size_t CMath::CVariableStack::size() const
{
  return mpStack->size();
}

const CEvaluationNode * CMath::CVariableStack::operator [](const size_t & index) const
{
  size_t Level = C_INVALID_INDEX;

  switch (mContext)
    {
      case Variable:
        Level = mVariableLevel;
        break;

      case Body:
        Level = mBodyLevel;

        break;
    }

  assert(Level < mpStack->size());
  assert(index < mpStack->at(Level).size());

  return mpStack->at(Level)[index];
}

std::ostream & operator << (std::ostream & os, const CMath::CVariableStack & s)
{
  switch (s.mContext)
    {
      case CMath::CVariableStack::Variable:
        os << "Context: variable ";
        break;

      case CMath::CVariableStack::Body:
        os << "Context: body ";
        break;
    }

  os << "Variable Level: " << s.mVariableLevel << " Body Level: " << s.mBodyLevel;

  return os;
}

CMath::CAllocationStack::CAllocation::CAllocation():
    nDiscontinuous(0),
    nTotalRoots(0),
    nRootsPerDiscontinuity()
{}

CMath::CAllocationStack::CAllocation::CAllocation(const CMath::CAllocationStack::CAllocation & src):
    nDiscontinuous(src.nDiscontinuous),
    nTotalRoots(src.nTotalRoots),
    nRootsPerDiscontinuity(src.nRootsPerDiscontinuity)
{}

CMath::CAllocationStack::CAllocation::~CAllocation()
{}

CMath::CAllocationStack::CAllocation::CAllocation &
CMath::CAllocationStack::CAllocation::operator = (const CMath::CAllocationStack::CAllocation::CAllocation & rhs)
{
  nDiscontinuous = rhs.nDiscontinuous;
  nTotalRoots = rhs.nTotalRoots;
  nRootsPerDiscontinuity = rhs.nRootsPerDiscontinuity;

  return *this;
}

CMath::CAllocationStack::CAllocation::CAllocation &
CMath::CAllocationStack::CAllocation::operator += (const CMath::CAllocationStack::CAllocation::CAllocation & rhs)
{
  nDiscontinuous += rhs.nDiscontinuous;
  nTotalRoots += rhs.nTotalRoots;
  nRootsPerDiscontinuity.insert(nRootsPerDiscontinuity.end(),
                                rhs.nRootsPerDiscontinuity.begin(),
                                rhs.nRootsPerDiscontinuity.end());

  return *this;
}

CMath::CAllocationStack::CAllocationStack():
    mpStack(NULL),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CAllocationStack::CAllocationStack(CMath::CAllocationStack::Buffer & stack):
    mpStack(&stack),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CAllocationStack::CAllocationStack(const CMath::CAllocationStack & src):
    mpStack(src.mpStack),
    mContext(src.mContext),
    mVariableLevel(src.mVariableLevel),
    mBodyLevel(src.mBodyLevel)
{}

CMath::CAllocationStack::~CAllocationStack()
{}

void CMath::CAllocationStack::push(const CMath::CAllocationStack::StackElement & stackElement)
{
  mpStack->push_back(stackElement);
  mBodyLevel++;
}

void CMath::CAllocationStack::pop()
{
  mpStack->pop_back();
  mBodyLevel--;
}

size_t CMath::CAllocationStack::size() const
{
  return mpStack->size();
}

const CMath::CAllocationStack::CAllocation &
CMath::CAllocationStack::operator [](const size_t & index) const
{
  size_t Level = C_INVALID_INDEX;

  switch (mContext)
    {
      case Variable:
        Level = mVariableLevel;
        break;

      case Body:
        Level = mBodyLevel;

        break;
    }

  assert(Level < mpStack->size());
  assert(index < mpStack->at(Level).size());

  return mpStack->at(Level)[index];
}

std::ostream & operator << (std::ostream & os, const CMath::CAllocationStack::CAllocation & s)
{
  os << "Discontinuities: " << s.nDiscontinuous;
  return os;
}

<commit_msg>Fixed to compile under Visual Studio 2005 (VC 8.0)<commit_after>// Begin CVS Header
//   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/math/CMathEnum.cpp,v $
//   $Revision: 1.2 $
//   $Name:  $
//   $Author: shoops $
//   $Date: 2011/06/07 19:59:41 $
// End CVS Header

// Copyright (C) 2011 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

#include "copasi.h"

#include "CMathEnum.h"

CMath::CVariableStack::CVariableStack():
    mpStack(NULL),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CVariableStack::CVariableStack(CMath::CVariableStack::Buffer & stack):
    mpStack(&stack),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CVariableStack::CVariableStack(const CMath::CVariableStack & src):
    mpStack(src.mpStack),
    mContext(src.mContext),
    mVariableLevel(src.mVariableLevel),
    mBodyLevel(src.mBodyLevel)
{}

CMath::CVariableStack::~CVariableStack()
{}

void CMath::CVariableStack::push(const CMath::CVariableStack::StackElement & stackElement)
{
  mpStack->push_back(stackElement);
  mBodyLevel++;
}

void CMath::CVariableStack::pop()
{
  mpStack->pop_back();
  mBodyLevel--;
}

size_t CMath::CVariableStack::size() const
{
  return mpStack->size();
}

const CEvaluationNode * CMath::CVariableStack::operator [](const size_t & index) const
{
  size_t Level = C_INVALID_INDEX;

  switch (mContext)
    {
      case Variable:
        Level = mVariableLevel;
        break;

      case Body:
        Level = mBodyLevel;

        break;
    }

  assert(Level < mpStack->size());
  assert(index < mpStack->at(Level).size());

  return mpStack->at(Level)[index];
}

std::ostream & operator << (std::ostream & os, const CMath::CVariableStack & s)
{
  switch (s.mContext)
    {
      case CMath::CVariableStack::Variable:
        os << "Context: variable ";
        break;

      case CMath::CVariableStack::Body:
        os << "Context: body ";
        break;
    }

  os << "Variable Level: " << s.mVariableLevel << " Body Level: " << s.mBodyLevel;

  return os;
}

CMath::CAllocationStack::CAllocation::CAllocation():
    nDiscontinuous(0),
    nTotalRoots(0),
    nRootsPerDiscontinuity()
{}

CMath::CAllocationStack::CAllocation::CAllocation(const CMath::CAllocationStack::CAllocation & src):
    nDiscontinuous(src.nDiscontinuous),
    nTotalRoots(src.nTotalRoots),
    nRootsPerDiscontinuity(src.nRootsPerDiscontinuity)
{}

CMath::CAllocationStack::CAllocation::~CAllocation()
{}

CMath::CAllocationStack::CAllocation &
CMath::CAllocationStack::CAllocation::operator = (const CMath::CAllocationStack::CAllocation & rhs)
{
  nDiscontinuous = rhs.nDiscontinuous;
  nTotalRoots = rhs.nTotalRoots;
  nRootsPerDiscontinuity = rhs.nRootsPerDiscontinuity;

  return *this;
}

CMath::CAllocationStack::CAllocation &
CMath::CAllocationStack::CAllocation::operator += (const CMath::CAllocationStack::CAllocation & rhs)
{
  nDiscontinuous += rhs.nDiscontinuous;
  nTotalRoots += rhs.nTotalRoots;
  nRootsPerDiscontinuity.insert(nRootsPerDiscontinuity.end(),
                                rhs.nRootsPerDiscontinuity.begin(),
                                rhs.nRootsPerDiscontinuity.end());

  return *this;
}

CMath::CAllocationStack::CAllocationStack():
    mpStack(NULL),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CAllocationStack::CAllocationStack(CMath::CAllocationStack::Buffer & stack):
    mpStack(&stack),
    mContext(Body),
    mVariableLevel(C_INVALID_INDEX),
    mBodyLevel(C_INVALID_INDEX)
{}

CMath::CAllocationStack::CAllocationStack(const CMath::CAllocationStack & src):
    mpStack(src.mpStack),
    mContext(src.mContext),
    mVariableLevel(src.mVariableLevel),
    mBodyLevel(src.mBodyLevel)
{}

CMath::CAllocationStack::~CAllocationStack()
{}

void CMath::CAllocationStack::push(const CMath::CAllocationStack::StackElement & stackElement)
{
  mpStack->push_back(stackElement);
  mBodyLevel++;
}

void CMath::CAllocationStack::pop()
{
  mpStack->pop_back();
  mBodyLevel--;
}

size_t CMath::CAllocationStack::size() const
{
  return mpStack->size();
}

const CMath::CAllocationStack::CAllocation &
CMath::CAllocationStack::operator [](const size_t & index) const
{
  size_t Level = C_INVALID_INDEX;

  switch (mContext)
    {
      case Variable:
        Level = mVariableLevel;
        break;

      case Body:
        Level = mBodyLevel;

        break;
    }

  assert(Level < mpStack->size());
  assert(index < mpStack->at(Level).size());

  return mpStack->at(Level)[index];
}

std::ostream & operator << (std::ostream & os, const CMath::CAllocationStack::CAllocation & s)
{
  os << "Discontinuities: " << s.nDiscontinuous;
  return os;
}

<|endoftext|>


<commit_before>/*
 * LoggingEvent.hh
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_LOGGINGEVENT_HH
#define _LOG4CPP_LOGGINGEVENT_HH

#include <string>
#include <time.h>

/**
 * The top level namespace for all 'Log for C++' types and classes.
 **/
namespace log4cpp {

/**
 * The internal representation of logging events. When a affirmative
 * logging decision is made a LoggingEvent instance is
 * created. This instance is passed around the different log4cpp
 * components.
 *
 *
This class is of concern to those wishing to extend log4cpp.
 **/

    struct LoggingEvent {
    public:
        /**
         * Instantiate a LoggingEvent from the supplied parameters.
         *
         *
Except timeStamp all the other fields of
         * LoggingEvent are filled when actually needed.
         *

         * @param category The category of this event.
         * @param message  The message of this event.
         * @param ndc The nested diagnostic context of this event.
         * @param priority The priority of this event.
         **/
        LoggingEvent(const std::string& category, const std::string& message,
                     const std::string& ndc, int priority);

        /** The category name. */
        const std::string& categoryName;

        /** The application supplied message of logging event. */
        const std::string& message;

        /** The nested diagnostic context (NDC) of logging event. */
        const std::string& ndc;

        /** Priority of logging event. */
        int priority;

        /** The name of thread in which this logging event was generated,
            e.g. the PID. */
        const std::string& threadName;
        //QQQ        const std::string threadName;

        /** The number of seconds elapsed since the epoch
            (1/1/1970 00:00:00 UTC) until logging event was created. */
        time_t timeStamp;
    };
}

#endif // _LOG4CPP_LOGGINGEVENT_HH

<commit_msg>Made threadName a member to keep MSVC++ from crashing.<commit_after>/*
 * LoggingEvent.hh
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_LOGGINGEVENT_HH
#define _LOG4CPP_LOGGINGEVENT_HH

#include <string>
#include <time.h>

/**
 * The top level namespace for all 'Log for C++' types and classes.
 **/
namespace log4cpp {

/**
 * The internal representation of logging events. When a affirmative
 * logging decision is made a LoggingEvent instance is
 * created. This instance is passed around the different log4cpp
 * components.
 *
 *
This class is of concern to those wishing to extend log4cpp.
 **/

    struct LoggingEvent {
    public:
        /**
         * Instantiate a LoggingEvent from the supplied parameters.
         *
         *
Except timeStamp all the other fields of
         * LoggingEvent are filled when actually needed.
         *

         * @param category The category of this event.
         * @param message  The message of this event.
         * @param ndc The nested diagnostic context of this event.
         * @param priority The priority of this event.
         **/
        LoggingEvent(const std::string& category, const std::string& message,
                     const std::string& ndc, int priority);

        /** The category name. */
        const std::string& categoryName;

        /** The application supplied message of logging event. */
        const std::string& message;

        /** The nested diagnostic context (NDC) of logging event. */
        const std::string& ndc;

        /** Priority of logging event. */
        int priority;

        /** The name of thread in which this logging event was generated,
            e.g. the PID. Because MSVC++ crashes if it is declared as a
            reference at this point I made it a member for now.
        */
        const std::string threadName;

        /** The number of seconds elapsed since the epoch
            (1/1/1970 00:00:00 UTC) until logging event was created. */
        time_t timeStamp;
    };
}

#endif // _LOG4CPP_LOGGINGEVENT_HH

<|endoftext|>


<commit_before>#ifndef GP_NODE_INTERFACE
#define GP_NODE_INTERFACE

#include <typeinfo>
#include <memory>
#include <any>
#include <utility/evaluation_context.hpp>
#include <utility/type.hpp>

namespace gp::node{
    enum class NodeType {
        Normal,
        Argument,
        LocalVariable,
        Progn,
        Subroutine,
        Const
    };

    //primary declarations for friend class declarations
    template <typename T>
    class NodeBase;
    template <typename T, std::size_t n>
    class PrognNode;

    class NodeInterface {
    public:
        using type_info = const utility::TypeInfo&;
        using node_instance_type = std::unique_ptr<NodeInterface>;
        template <typename NodeType, typename ...Ts>
        static node_instance_type createInstance(Ts&&... args) {return std::make_unique<NodeType>(std::forward<Ts>(args)...);}
    private:
        template <typename T> friend class NodeBase;
        template <typename T, std::size_t n> friend class PrognNode;
        virtual void setParent(NodeInterface* node) = 0;
    public:
        //type information methods
        virtual type_info getReturnType()const noexcept= 0;
        virtual type_info getChildReturnType(std::size_t n)const noexcept = 0;
        //methods for children
        virtual std::size_t getChildNum()const noexcept = 0;
        virtual bool hasChild(std::size_t n)const noexcept = 0;
        virtual NodeInterface& getChildNode(std::size_t n) = 0;
        virtual const NodeInterface& getChildNode(std::size_t n)const = 0;
        virtual void setChild(std::size_t n, std::unique_ptr<NodeInterface> node) = 0;
        //methods for parent
        virtual bool hasParent()const noexcept = 0;
        virtual NodeInterface& getParent() = 0;
        virtual const NodeInterface& getParent()const = 0;
        //method for evaluation
        virtual std::any evaluateByAny(utility::EvaluationContext&)const = 0;
        //methods for properties
        virtual void setNodePropertyByNodeName(const std::string&) = 0;
        virtual void setNodePropertyByAny(const std::any&) = 0;
        virtual std::any getNodePropertyByAny()const = 0;
        virtual std::string getNodeName()const = 0;
        virtual node_instance_type clone()const = 0;
        virtual NodeType getNodeType()const noexcept = 0;
    public:
        virtual ~NodeInterface() = default;
        NodeInterface(NodeInterface&&) = default;
        NodeInterface& operator=(NodeInterface&&) = default;
        NodeInterface(const NodeInterface&) = default;
        NodeInterface& operator=(const NodeInterface&) = default;
        NodeInterface() = default;
    };
}

#endif<commit_msg>force users to derive TypedNodeInterface by setting the constructor of NodeInterface as private<commit_after>#ifndef GP_NODE_INTERFACE
#define GP_NODE_INTERFACE

#include <typeinfo>
#include <memory>
#include <any>
#include <utility/evaluation_context.hpp>
#include <utility/type.hpp>

namespace gp::node{
    enum class NodeType {
        Normal,
        Argument,
        LocalVariable,
        Progn,
        Subroutine,
        Const
    };

    //primary declarations for friend class declarations
    template <typename T>
    class TypedNodeInterface;
    template <typename T>
    class NodeBase;
    template <typename T, std::size_t n>
    class PrognNode;

    class NodeInterface {
    public:
        using type_info = const utility::TypeInfo&;
        using node_instance_type = std::unique_ptr<NodeInterface>;
        template <typename NodeType, typename ...Ts>
        static node_instance_type createInstance(Ts&&... args) {return std::make_unique<NodeType>(std::forward<Ts>(args)...);}
    private:
        template <typename T> friend class TypedNodeInterface;
        template <typename T> friend class NodeBase;
        template <typename T, std::size_t n> friend class PrognNode;
        NodeInterface() = default; //only the TypedNodeInterface can construct NodeInterface. Users who want to create custom node must derive NodeBase or TypedNodeInterface.
        virtual void setParent(NodeInterface* node) = 0;
    public:
        //type information methods
        virtual type_info getReturnType()const noexcept= 0;
        virtual type_info getChildReturnType(std::size_t n)const noexcept = 0;
        //methods for children
        virtual std::size_t getChildNum()const noexcept = 0;
        virtual bool hasChild(std::size_t n)const noexcept = 0;
        virtual NodeInterface& getChildNode(std::size_t n) = 0;
        virtual const NodeInterface& getChildNode(std::size_t n)const = 0;
        virtual void setChild(std::size_t n, std::unique_ptr<NodeInterface> node) = 0;
        //methods for parent
        virtual bool hasParent()const noexcept = 0;
        virtual NodeInterface& getParent() = 0;
        virtual const NodeInterface& getParent()const = 0;
        //method for evaluation
        virtual std::any evaluateByAny(utility::EvaluationContext&)const = 0;
        //methods for properties
        virtual void setNodePropertyByNodeName(const std::string&) = 0;
        virtual void setNodePropertyByAny(const std::any&) = 0;
        virtual std::any getNodePropertyByAny()const = 0;
        virtual std::string getNodeName()const = 0;
        virtual node_instance_type clone()const = 0;
        virtual NodeType getNodeType()const noexcept = 0;
    public:
        virtual ~NodeInterface() = default;
        NodeInterface(NodeInterface&&) = default;
        NodeInterface& operator=(NodeInterface&&) = default;
        NodeInterface(const NodeInterface&) = default;
        NodeInterface& operator=(const NodeInterface&) = default;
    };
}

#endif<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/subtransaction.hxx
 *
 *   DESCRIPTION
 *      definition of the pqxx::subtransaction class.
 *   pqxx::subtransaction is a nested transaction, i.e. one within a transaction
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.
 *
 * Copyright (c) 2005, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler-public.hxx"

#include "pqxx/dbtransaction"

/* Methods tested in eg. self-test program test1 are marked with "//[t1]"
 */

namespace pqxx
{

/**
 * @addtogroup transaction Transaction classes
 */
//@{

class PQXX_LIBEXPORT subtransaction :
  public internal::transactionfocus,
  public dbtransaction
{
public:
  explicit subtransaction(dbtransaction &T,
	const PGSTD::string &Name=PGSTD::string());			//[t88]

private:
  virtual void do_begin();						//[t88]
  virtual void do_commit();						//[t88]
  virtual void do_abort();						//[t88]

  dbtransaction &m_parent;
};

//@}

}

<commit_msg>Smarter detection of backend capability<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/subtransaction.hxx
 *
 *   DESCRIPTION
 *      definition of the pqxx::subtransaction class.
 *   pqxx::subtransaction is a nested transaction, i.e. one within a transaction
 *   DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/subtransaction instead.
 *
 * Copyright (c) 2005-2006, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler-public.hxx"

#include "pqxx/dbtransaction"

/* Methods tested in eg. self-test program test1 are marked with "//[t1]"
 */

namespace pqxx
{

/**
 * @addtogroup transaction Transaction classes
 */
//@{

class PQXX_LIBEXPORT subtransaction :
  public internal::transactionfocus,
  public dbtransaction
{
public:
  explicit subtransaction(dbtransaction &T,
	const PGSTD::string &Name=PGSTD::string());			//[t88]

private:
  virtual void do_begin();						//[t88]
  virtual void do_commit();						//[t88]
  virtual void do_abort();						//[t88]

  void check_backendsupport() const;

  dbtransaction &m_parent;
};

//@}

}

<|endoftext|>


<commit_before>// Copyright (c) 2008, Google 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:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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 "ScrollbarThemeChromium.h"

#include "AffineTransform.h"
#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "PlatformMouseEvent.h"
#include "Scrollbar.h"

#include "gtkdrawing.h"
#include "GdkSkia.h"
#include <gtk/gtk.h>

namespace WebCore {

int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
{
    static int size = 0;
    if (!size) {
        MozGtkScrollbarMetrics metrics;
        moz_gtk_get_scrollbar_metrics(&metrics);
        size = metrics.slider_width;
    }
    return size;
}

bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
{
    notImplemented();
    return false;
}

// -----------------------------------------------------------------------------
// Given an uninitialised widget state object, set the members such that it's
// sane for drawing scrollbars
// -----------------------------------------------------------------------------
static void initMozState(GtkWidgetState* mozState)
{
    mozState->active = true;
    mozState->focused = false;
    mozState->inHover = false;
    mozState->disabled = false;
    mozState->isDefault = false;
    mozState->canDefault = false;
    mozState->depressed = false;
    mozState->curpos = 0;
    mozState->maxpos = 0;
}

// -----------------------------------------------------------------------------
// Paint a GTK widget
//   gc: context to draw onto
//   rect: the area of the widget
//   widget_type: the type of widget to draw
//   flags: widget dependent flags (e.g. direction of scrollbar arrows etc)
//
// See paintMozWiget in RenderThemeGtk.cpp for an explanation of the clipping.
// -----------------------------------------------------------------------------
static void paintScrollbarWidget(GraphicsContext* gc, const IntRect& rect,
                                 GtkThemeWidgetType widget_type, gint flags)
{
    PlatformContextSkia* pcs = gc->platformContext();

    GdkRectangle gdkRect = { rect.x(), rect.y(), rect.width(), rect.height() };

    const SkIRect clip_region = pcs->canvas()->getTotalClip().getBounds();
    AffineTransform ctm = gc->getCTM().inverse();
    IntPoint pos = ctm.mapPoint(
        IntPoint(SkScalarRound(clip_region.fLeft), SkScalarRound(clip_region.fTop)));
    GdkRectangle gdkClipRect;
    gdkClipRect.x = pos.x();
    gdkClipRect.y = pos.y();
    gdkClipRect.width = clip_region.width();
    gdkClipRect.height = clip_region.height();

    gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect);

    GtkWidgetState mozState;
    initMozState(&mozState);

    moz_gtk_widget_paint(widget_type, pcs->gdk_skia(), &gdkRect, &gdkClipRect,
                         &mozState, flags, GTK_TEXT_DIR_LTR);
}

void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar,
                                             const IntRect& rect, ScrollbarPart partType)
{
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    const GtkThemeWidgetType track_type =
        horz ? MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL : MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
    paintScrollbarWidget(gc, rect, track_type, 0);

    return;
}

void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar,
                                    const IntRect& rect, ScrollbarPart part)
{
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    gint flags = horz ? 0 : MOZ_GTK_STEPPER_VERTICAL;
    flags |= ForwardButtonEndPart == part ? MOZ_GTK_STEPPER_DOWN : 0;
    paintScrollbarWidget(gc, rect, MOZ_GTK_SCROLLBAR_BUTTON, flags);
}

void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
{
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    const GtkThemeWidgetType thumb_type =
        horz ? MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL : MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
    paintScrollbarWidget(gc, rect, thumb_type, 0);
}

}  // namespace WebCore
<commit_msg>It appears that the GTK theme doesn't always draw the full rectangle when we ask it to draw a scrollbar button. It's not clear if it expects the background to already be filled in, or if we are brearking it by giving it WebKit metrics. Either way, it's messing up our pixeltest baselines with undefined pixels so we paint seafoam-green under scrollbar buttons before GTK draws.<commit_after>// Copyright (c) 2008, Google 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:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "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 THE COPYRIGHT
// OWNER 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 "ScrollbarThemeChromium.h"

#include "AffineTransform.h"
#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "PlatformMouseEvent.h"
#include "Scrollbar.h"

#include "gtkdrawing.h"
#include "GdkSkia.h"
#include <gtk/gtk.h>

namespace WebCore {

int ScrollbarThemeChromium::scrollbarThickness(ScrollbarControlSize controlSize)
{
    static int size = 0;
    if (!size) {
        MozGtkScrollbarMetrics metrics;
        moz_gtk_get_scrollbar_metrics(&metrics);
        size = metrics.slider_width;
    }
    return size;
}

bool ScrollbarThemeChromium::invalidateOnMouseEnterExit()
{
    notImplemented();
    return false;
}

// -----------------------------------------------------------------------------
// Given an uninitialised widget state object, set the members such that it's
// sane for drawing scrollbars
// -----------------------------------------------------------------------------
static void initMozState(GtkWidgetState* mozState)
{
    mozState->active = true;
    mozState->focused = false;
    mozState->inHover = false;
    mozState->disabled = false;
    mozState->isDefault = false;
    mozState->canDefault = false;
    mozState->depressed = false;
    mozState->curpos = 0;
    mozState->maxpos = 0;
}

// -----------------------------------------------------------------------------
// Paint a GTK widget
//   gc: context to draw onto
//   rect: the area of the widget
//   widget_type: the type of widget to draw
//   flags: widget dependent flags (e.g. direction of scrollbar arrows etc)
//
// See paintMozWiget in RenderThemeGtk.cpp for an explanation of the clipping.
// -----------------------------------------------------------------------------
static void paintScrollbarWidget(GraphicsContext* gc, const IntRect& rect,
                                 GtkThemeWidgetType widget_type, gint flags)
{
    PlatformContextSkia* pcs = gc->platformContext();

    GdkRectangle gdkRect = { rect.x(), rect.y(), rect.width(), rect.height() };

    const SkIRect clip_region = pcs->canvas()->getTotalClip().getBounds();
    AffineTransform ctm = gc->getCTM().inverse();
    IntPoint pos = ctm.mapPoint(
        IntPoint(SkScalarRound(clip_region.fLeft), SkScalarRound(clip_region.fTop)));
    GdkRectangle gdkClipRect;
    gdkClipRect.x = pos.x();
    gdkClipRect.y = pos.y();
    gdkClipRect.width = clip_region.width();
    gdkClipRect.height = clip_region.height();

    gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect);

    GtkWidgetState mozState;
    initMozState(&mozState);

    moz_gtk_widget_paint(widget_type, pcs->gdk_skia(), &gdkRect, &gdkClipRect,
                         &mozState, flags, GTK_TEXT_DIR_LTR);
}

void ScrollbarThemeChromium::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar,
                                             const IntRect& rect, ScrollbarPart partType)
{
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    const GtkThemeWidgetType track_type =
        horz ? MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL : MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
    paintScrollbarWidget(gc, rect, track_type, 0);

    return;
}

void ScrollbarThemeChromium::paintButton(GraphicsContext* gc, Scrollbar* scrollbar,
                                    const IntRect& rect, ScrollbarPart part)
{
    // TODO(port): It appears the either we're upsetting GTK by forcing WebKit
    // sizes on it, or the buttons expect the track to be drawn under them.
    // Either way, we end up with unpainted pixels which are upsetting the
    // pixel tests. Thus we paint green under the buttons to, at least, make
    // the pixel output the same between debug and opt builds.
    SkPaint paint;
    paint.setARGB(255, 0, 255, 128);
    SkRect skrect;
    skrect.set(rect.x(), rect.y(), rect.x() + rect.width() - 1, rect.y() + rect.height() + 1);
    gc->platformContext()->canvas()->drawRect(skrect, paint);

    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    gint flags = horz ? 0 : MOZ_GTK_STEPPER_VERTICAL;
    flags |= ForwardButtonEndPart == part ? MOZ_GTK_STEPPER_DOWN : 0;
    paintScrollbarWidget(gc, rect, MOZ_GTK_SCROLLBAR_BUTTON, flags);
}

void ScrollbarThemeChromium::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
{
    const bool horz = scrollbar->orientation() == HorizontalScrollbar;
    const GtkThemeWidgetType thumb_type =
        horz ? MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL : MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
    paintScrollbarWidget(gc, rect, thumb_type, 0);
}

}  // namespace WebCore
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

//
// request.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include <seastar/core/iostream.hh>
#include <seastar/core/sstring.hh>
#include <string>
#include <vector>
#include <strings.h>
#include <seastar/http/common.hh>
#include <seastar/core/iostream.hh>

namespace seastar {

namespace httpd {
class connection;

/**
 * A request received from a client.
 */
struct request {
    enum class ctclass
        : char {
            other, multipart, app_x_www_urlencoded,
    };

    struct case_insensitive_cmp {
        bool operator()(const sstring& s1, const sstring& s2) const {
            return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(),
                    [](char a, char b) { return ::tolower(a) == ::tolower(b); });
        }
    };

    struct case_insensitive_hash {
        size_t operator()(sstring s) const {
            std::transform(s.begin(), s.end(), s.begin(), ::tolower);
            return std::hash<sstring>()(s);
        }
    };

    sstring _method;
    sstring _url;
    sstring _version;
    int http_version_major;
    int http_version_minor;
    ctclass content_type_class;
    size_t content_length = 0;
    std::unordered_map<sstring, sstring, case_insensitive_hash, case_insensitive_cmp> _headers;
    std::unordered_map<sstring, sstring> query_parameters;
    connection* connection_ptr;
    parameters param;
    sstring content; // deprecated: use content_stream instead
    /*
     * The handler should read the contents of this stream till reaching eof (i.e., the end of this request's content). Failing to do so
     * will force the server to close this connection, and the client will not be able to reuse this connection for the next request.
     * The stream should not be closed by the handler, the server will close it for the handler.
     * */
    input_stream<char>* content_stream;
    std::unordered_map<sstring, sstring> trailing_headers;
    std::unordered_map<sstring, sstring> chunk_extensions;
    sstring protocol_name = "http";

    /**
     * Search for the first header of a given name
     * @param name the header name
     * @return a pointer to the header value, if it exists or empty string
     */
    sstring get_header(const sstring& name) const {
        auto res = _headers.find(name);
        if (res == _headers.end()) {
            return "";
        }
        return res->second;
    }

    /**
     * Search for the first header of a given name
     * @param name the header name
     * @return a pointer to the header value, if it exists or empty string
     */
    sstring get_query_param(const sstring& name) const {
        auto res = query_parameters.find(name);
        if (res == query_parameters.end()) {
            return "";
        }
        return res->second;
    }

    /**
     * Get the request protocol name. Can be either "http" or "https".
     */
    sstring get_protocol_name() const {
        return protocol_name;
    }

    /**
     * Get the request url.
     * @return the request url
     */
    sstring get_url() const {
        return get_protocol_name() + "://" + get_header("Host") + _url;
    }

    bool is_multi_part() const {
        return content_type_class == ctclass::multipart;
    }

    bool is_form_post() const {
        return content_type_class == ctclass::app_x_www_urlencoded;
    }

    bool should_keep_alive() const {
        if (_version == "0.9") {
            return false;
        }

        // TODO: handle HTTP/2.0 when it releases

        auto it = _headers.find("Connection");
        if (_version == "1.0") {
            return it != _headers.end()
                 && case_insensitive_cmp()(it->second, "keep-alive");
        } else { // HTTP/1.1
            return it == _headers.end() || !case_insensitive_cmp()(it->second, "close");
        }
    }
};

} // namespace httpd

}
<commit_msg>http: Remove unused members from request<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright 2015 Cloudius Systems
 */

//
// request.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include <seastar/core/iostream.hh>
#include <seastar/core/sstring.hh>
#include <string>
#include <vector>
#include <strings.h>
#include <seastar/http/common.hh>
#include <seastar/core/iostream.hh>

namespace seastar {

namespace httpd {

/**
 * A request received from a client.
 */
struct request {
    enum class ctclass
        : char {
            other, multipart, app_x_www_urlencoded,
    };

    struct case_insensitive_cmp {
        bool operator()(const sstring& s1, const sstring& s2) const {
            return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(),
                    [](char a, char b) { return ::tolower(a) == ::tolower(b); });
        }
    };

    struct case_insensitive_hash {
        size_t operator()(sstring s) const {
            std::transform(s.begin(), s.end(), s.begin(), ::tolower);
            return std::hash<sstring>()(s);
        }
    };

    sstring _method;
    sstring _url;
    sstring _version;
    ctclass content_type_class;
    size_t content_length = 0;
    std::unordered_map<sstring, sstring, case_insensitive_hash, case_insensitive_cmp> _headers;
    std::unordered_map<sstring, sstring> query_parameters;
    parameters param;
    sstring content; // deprecated: use content_stream instead
    /*
     * The handler should read the contents of this stream till reaching eof (i.e., the end of this request's content). Failing to do so
     * will force the server to close this connection, and the client will not be able to reuse this connection for the next request.
     * The stream should not be closed by the handler, the server will close it for the handler.
     * */
    input_stream<char>* content_stream;
    std::unordered_map<sstring, sstring> trailing_headers;
    std::unordered_map<sstring, sstring> chunk_extensions;
    sstring protocol_name = "http";

    /**
     * Search for the first header of a given name
     * @param name the header name
     * @return a pointer to the header value, if it exists or empty string
     */
    sstring get_header(const sstring& name) const {
        auto res = _headers.find(name);
        if (res == _headers.end()) {
            return "";
        }
        return res->second;
    }

    /**
     * Search for the first header of a given name
     * @param name the header name
     * @return a pointer to the header value, if it exists or empty string
     */
    sstring get_query_param(const sstring& name) const {
        auto res = query_parameters.find(name);
        if (res == query_parameters.end()) {
            return "";
        }
        return res->second;
    }

    /**
     * Get the request protocol name. Can be either "http" or "https".
     */
    sstring get_protocol_name() const {
        return protocol_name;
    }

    /**
     * Get the request url.
     * @return the request url
     */
    sstring get_url() const {
        return get_protocol_name() + "://" + get_header("Host") + _url;
    }

    bool is_multi_part() const {
        return content_type_class == ctclass::multipart;
    }

    bool is_form_post() const {
        return content_type_class == ctclass::app_x_www_urlencoded;
    }

    bool should_keep_alive() const {
        if (_version == "0.9") {
            return false;
        }

        // TODO: handle HTTP/2.0 when it releases

        auto it = _headers.find("Connection");
        if (_version == "1.0") {
            return it != _headers.end()
                 && case_insensitive_cmp()(it->second, "keep-alive");
        } else { // HTTP/1.1
            return it == _headers.end() || !case_insensitive_cmp()(it->second, "close");
        }
    }
};

} // namespace httpd

}
<|endoftext|>


<commit_before>#include <nsIFactory.h>

#include "sugar-download-manager.h"

#include "GeckoDownload.h"

class GeckoDownload : public nsITransfer
{
public:
    GeckoDownload();
	virtual ~GeckoDownload();

	NS_DECL_ISUPPORTS
	NS_DECL_NSIWEBPROGRESSLISTENER
	NS_DECL_NSIWEBPROGRESSLISTENER2
	NS_DECL_NSITRANSFER

protected:
	nsIURI			*mSource;
	nsCString		mTargetFileName;
	nsIMIMEInfo		*mMIMEInfo;
	nsILocalFile	*mTempFile;
};

GeckoDownload::GeckoDownload ()
{
}

GeckoDownload::~GeckoDownload ()
{
}

NS_IMPL_ISUPPORTS3 (GeckoDownload,
					nsIWebProgressListener,
					nsIWebProgressListener2,
					nsITransfer)

NS_IMETHODIMP
GeckoDownload::Init (nsIURI *aSource,
					 nsIURI *aTarget,
					 const nsAString &aDisplayName,
					 nsIMIMEInfo *aMIMEInfo,
					 PRTime aStartTime,
					 nsILocalFile *aTempFile,
					 nsICancelable *aCancelable)
{
	mSource = aSource;
	aTarget->GetPath (mTargetFileName);
	mMIMEInfo = aMIMEInfo;
	mTempFile = aTempFile;
//	mCancelable = aCancelable;	Just a reminder for when we implement cancelling downloads.

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnStateChange (nsIWebProgress *aWebProgress,
							  nsIRequest *aRequest,
							  PRUint32 aStateFlags,
							  nsresult aStatus)
{
	SugarDownloadManager *download_manager = sugar_get_download_manager ();

	if (aStateFlags == STATE_START) {

		nsCString url;
		nsCString mimeType;

		mMIMEInfo->GetMIMEType (mimeType);
		mSource->GetSpec (url);

		sugar_download_manager_download_started (download_manager,
												 url.get (),
												 mimeType.get (),
												 mTargetFileName.get ());

	} else if (aStateFlags == STATE_STOP) {

		if (NS_SUCCEEDED (aStatus)) {
			sugar_download_manager_download_completed (download_manager,
													   mTargetFileName.get ());
		} else {
			sugar_download_manager_download_cancelled (download_manager,
													   mTargetFileName.get ());
		}
	}

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnProgressChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 PRInt32 aCurSelfProgress,
								 PRInt32 aMaxSelfProgress,
								 PRInt32 aCurTotalProgress,
								 PRInt32 aMaxTotalProgress)
{
	return OnProgressChange64 (aWebProgress,
							   aRequest,
							   aCurSelfProgress,
							   aMaxSelfProgress,
							   aCurTotalProgress,
							   aMaxTotalProgress);
}

NS_IMETHODIMP
GeckoDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
								   nsIRequest *aRequest,
								   PRInt64 aCurSelfProgress,
								   PRInt64 aMaxSelfProgress,
								   PRInt64 aCurTotalProgress,
								   PRInt64 aMaxTotalProgress)
{
	SugarDownloadManager *download_manager = sugar_get_download_manager ();
	PRInt32 percentComplete =
		(PRInt32)(((float)aCurSelfProgress / (float)aMaxSelfProgress) * 100.0);

	sugar_download_manager_update_progress (download_manager,
											mTargetFileName.get (),
											percentComplete);

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnLocationChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 nsIURI *location)
{
	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnStatusChange (nsIWebProgress *aWebProgress,
							   nsIRequest *aRequest,
							   nsresult aStatus,
							   const PRUnichar *aMessage)
{
	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnSecurityChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 PRUint32 state)
{
	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnRefreshAttempted (nsIWebProgress *aWebProgress,
                                   nsIURI *aRefreshURI,
                                   PRInt32 aMillis,
                                   PRBool aSameURI,
                                   PRBool *_retval)
{
	return NS_OK;
}
//*****************************************************************************
// GeckoDownloadFactory
//*****************************************************************************

class GeckoDownloadFactory : public nsIFactory {
public:
    NS_DECL_ISUPPORTS
    NS_DECL_NSIFACTORY

    GeckoDownloadFactory();
    virtual ~GeckoDownloadFactory();
};

//*****************************************************************************

NS_IMPL_ISUPPORTS1(GeckoDownloadFactory, nsIFactory)

GeckoDownloadFactory::GeckoDownloadFactory() {
}

GeckoDownloadFactory::~GeckoDownloadFactory() {
}

NS_IMETHODIMP
GeckoDownloadFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult)
{
    NS_ENSURE_ARG_POINTER(aResult);

    *aResult = NULL;
    GeckoDownload *inst = new GeckoDownload;
    if (!inst)
        return NS_ERROR_OUT_OF_MEMORY;

    nsresult rv = inst->QueryInterface(aIID, aResult);
    if (rv != NS_OK) {
        // We didn't get the right interface, so clean up
        delete inst;
    }

    return rv;
}

NS_IMETHODIMP
GeckoDownloadFactory::LockFactory(PRBool lock)
{
    return NS_OK;
}

//*****************************************************************************

nsresult
NS_NewGeckoDownloadFactory(nsIFactory** aFactory)
{
    NS_ENSURE_ARG_POINTER(aFactory);
    *aFactory = nsnull;

    GeckoDownloadFactory *result = new GeckoDownloadFactory;
    if (!result)
        return NS_ERROR_OUT_OF_MEMORY;

    NS_ADDREF(result);
    *aFactory = result;

    return NS_OK;
}
<commit_msg>Compile the new method only if we are on 1.9<commit_after>#include <nsIFactory.h>

#include "sugar-download-manager.h"

#include "GeckoDownload.h"

class GeckoDownload : public nsITransfer
{
public:
    GeckoDownload();
	virtual ~GeckoDownload();

	NS_DECL_ISUPPORTS
	NS_DECL_NSIWEBPROGRESSLISTENER
	NS_DECL_NSIWEBPROGRESSLISTENER2
	NS_DECL_NSITRANSFER

protected:
	nsIURI			*mSource;
	nsCString		mTargetFileName;
	nsIMIMEInfo		*mMIMEInfo;
	nsILocalFile	*mTempFile;
};

GeckoDownload::GeckoDownload ()
{
}

GeckoDownload::~GeckoDownload ()
{
}

NS_IMPL_ISUPPORTS3 (GeckoDownload,
					nsIWebProgressListener,
					nsIWebProgressListener2,
					nsITransfer)

NS_IMETHODIMP
GeckoDownload::Init (nsIURI *aSource,
					 nsIURI *aTarget,
					 const nsAString &aDisplayName,
					 nsIMIMEInfo *aMIMEInfo,
					 PRTime aStartTime,
					 nsILocalFile *aTempFile,
					 nsICancelable *aCancelable)
{
	mSource = aSource;
	aTarget->GetPath (mTargetFileName);
	mMIMEInfo = aMIMEInfo;
	mTempFile = aTempFile;
//	mCancelable = aCancelable;	Just a reminder for when we implement cancelling downloads.

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnStateChange (nsIWebProgress *aWebProgress,
							  nsIRequest *aRequest,
							  PRUint32 aStateFlags,
							  nsresult aStatus)
{
	SugarDownloadManager *download_manager = sugar_get_download_manager ();

	if (aStateFlags == STATE_START) {

		nsCString url;
		nsCString mimeType;

		mMIMEInfo->GetMIMEType (mimeType);
		mSource->GetSpec (url);

		sugar_download_manager_download_started (download_manager,
												 url.get (),
												 mimeType.get (),
												 mTargetFileName.get ());

	} else if (aStateFlags == STATE_STOP) {

		if (NS_SUCCEEDED (aStatus)) {
			sugar_download_manager_download_completed (download_manager,
													   mTargetFileName.get ());
		} else {
			sugar_download_manager_download_cancelled (download_manager,
													   mTargetFileName.get ());
		}
	}

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnProgressChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 PRInt32 aCurSelfProgress,
								 PRInt32 aMaxSelfProgress,
								 PRInt32 aCurTotalProgress,
								 PRInt32 aMaxTotalProgress)
{
	return OnProgressChange64 (aWebProgress,
							   aRequest,
							   aCurSelfProgress,
							   aMaxSelfProgress,
							   aCurTotalProgress,
							   aMaxTotalProgress);
}

NS_IMETHODIMP
GeckoDownload::OnProgressChange64 (nsIWebProgress *aWebProgress,
								   nsIRequest *aRequest,
								   PRInt64 aCurSelfProgress,
								   PRInt64 aMaxSelfProgress,
								   PRInt64 aCurTotalProgress,
								   PRInt64 aMaxTotalProgress)
{
	SugarDownloadManager *download_manager = sugar_get_download_manager ();
	PRInt32 percentComplete =
		(PRInt32)(((float)aCurSelfProgress / (float)aMaxSelfProgress) * 100.0);

	sugar_download_manager_update_progress (download_manager,
											mTargetFileName.get (),
											percentComplete);

	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnLocationChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 nsIURI *location)
{
	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnStatusChange (nsIWebProgress *aWebProgress,
							   nsIRequest *aRequest,
							   nsresult aStatus,
							   const PRUnichar *aMessage)
{
	return NS_OK;
}

NS_IMETHODIMP
GeckoDownload::OnSecurityChange (nsIWebProgress *aWebProgress,
								 nsIRequest *aRequest,
								 PRUint32 state)
{
	return NS_OK;
}

#ifdef HAVE_MOZILLA_1_9

NS_IMETHODIMP
GeckoDownload::OnRefreshAttempted (nsIWebProgress *aWebProgress,
                                   nsIURI *aRefreshURI,
                                   PRInt32 aMillis,
                                   PRBool aSameURI,
                                   PRBool *_retval)
{
	return NS_OK;
}

#endif

//*****************************************************************************
// GeckoDownloadFactory
//*****************************************************************************

class GeckoDownloadFactory : public nsIFactory {
public:
    NS_DECL_ISUPPORTS
    NS_DECL_NSIFACTORY

    GeckoDownloadFactory();
    virtual ~GeckoDownloadFactory();
};

//*****************************************************************************

NS_IMPL_ISUPPORTS1(GeckoDownloadFactory, nsIFactory)

GeckoDownloadFactory::GeckoDownloadFactory() {
}

GeckoDownloadFactory::~GeckoDownloadFactory() {
}

NS_IMETHODIMP
GeckoDownloadFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult)
{
    NS_ENSURE_ARG_POINTER(aResult);

    *aResult = NULL;
    GeckoDownload *inst = new GeckoDownload;
    if (!inst)
        return NS_ERROR_OUT_OF_MEMORY;

    nsresult rv = inst->QueryInterface(aIID, aResult);
    if (rv != NS_OK) {
        // We didn't get the right interface, so clean up
        delete inst;
    }

    return rv;
}

NS_IMETHODIMP
GeckoDownloadFactory::LockFactory(PRBool lock)
{
    return NS_OK;
}

//*****************************************************************************

nsresult
NS_NewGeckoDownloadFactory(nsIFactory** aFactory)
{
    NS_ENSURE_ARG_POINTER(aFactory);
    *aFactory = nsnull;

    GeckoDownloadFactory *result = new GeckoDownloadFactory;
    if (!result)
        return NS_ERROR_OUT_OF_MEMORY;

    NS_ADDREF(result);
    *aFactory = result;

    return NS_OK;
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/exceptions.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>

#include <bh_config_parser.hpp>

#ifdef _WIN32

#include <windows.h>
#include <dlfcn-win32.h>

#define HOME_INI_PATH "%APPDATA%\\bohrium\\config.ini"
#define SYSTEM_INI_PATH_1 "%PROGRAMFILES%\\bohrium\\config.ini"
#define SYSTEM_INI_PATH_2 "%PROGRAMFILES%\\bohrium\\config.ini"

//Nasty function renaming
#define snprintf _snprintf
#define strcasecmp _stricmp

#else

#include <dlfcn.h>
#include <limits.h>

#define HOME_INI_PATH "~/.bohrium/config.ini"
#define SYSTEM_INI_PATH_1 "/usr/local/etc/bohrium/config.ini"
#define SYSTEM_INI_PATH_2 "/usr/etc/bohrium/config.ini"

#endif

using namespace std;
using namespace boost;

namespace bohrium {

namespace {
// Path to the config file e.g. ~/.bohrium/config.ini
string get_config_path() {

    const char* homepath = HOME_INI_PATH;
    const char* syspath1 = SYSTEM_INI_PATH_1;
    const char* syspath2 = SYSTEM_INI_PATH_2;

    //
    // Find the configuration file
    //

    // Start by looking a path set via environment variable.
    const char *env = getenv("BH_CONFIG");
    if (env != NULL)
    {
        FILE *fp = fopen(env,"r");
        if( fp )
            fclose(fp);
        else
            env = NULL;//Did not exist.
    }

    // Then the home directory.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            homepath,
            _expand_buffer,
            MAX_PATH-1
        );

        if (result != 0)
        {
            homepath = _expand_buffer;
        }
#else
        char* h = getenv("HOME");
        if (h != NULL)
        {
            char _expand_buffer[PATH_MAX];
            snprintf(_expand_buffer, PATH_MAX, "%s/%s", h, homepath+1);
            homepath = _expand_buffer;
        }
#endif
        FILE *fp = fopen(homepath,"r");
        if( fp ) {
            env = homepath;
            fclose(fp);
        }
    }

    //And then system-wide.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            syspath1,
            _expand_buffer,
            MAX_PATH-1
        );

        if(result != 0)
        {
            syspath1 = _expand_buffer;
        }
#endif
        FILE *fp = fopen(syspath1,"r");
        if(fp)
        {
            env = syspath1;
            fclose(fp);
        }
    }

    //And then system-wide.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            syspath2,
            _expand_buffer,
            MAX_PATH-1
        );

        if(result != 0)
        {
            syspath2 = _expand_buffer;
        }
#endif
        FILE *fp = fopen(syspath2,"r");
        if(fp)
        {
            env = syspath2;
            fclose(fp);
        }
    }
    // We could not find the configuration file anywhere
    if(env == NULL)
    {
        fprintf(stderr, "Error: Bohrium could not find the config file.\n"
            " The search is:\n"
            "\t* The environment variable BH_CONFIG.\n"
            "\t* The home directory \"%s\".\n"
            "\t* The local directory \"%s\".\n"
            "\t* And system-wide \"%s\".\n", homepath, syspath1, syspath2);
        throw invalid_argument("No config file");
    }
    return string(env);
}

// Return section/option as an environment variable
// or the empty string if the environment variable wasn't found
string lookup_env(const string &section, const string &option) {
    string s = "BH_" + section + "_" + option;
    to_upper(s);
    const char *env = getenv(s.c_str());

    if (env == NULL) {
        return string();
    } else {
        return string(env);
    }
}

}// namespace unnamed

string ConfigParser::lookup(const string &section, const string &option) const {
    //Check environment variable
    string ret = lookup_env(section, option);
    if (not ret.empty())
        return ret;

    //Check config file
    ret = _config.get<string>(section + "." + option);

    //Remove quotes "" or '' and return
    if (ret.find_first_of("\"'") == 0 and ret.find_last_of("\"'") == ret.size()-1) {
        return ret.substr(1, ret.size()-2);
    } else {
        return ret;
    }
}

ConfigParser::ConfigParser(int stack_level) : file_path(get_config_path()),
                                              stack_level(stack_level) {

    // Load the bohrium configuration file
    property_tree::ini_parser::read_ini(file_path, _config);

    // Find the stack name specified by 'BH_STACK'
    const char *env = getenv("BH_STACK");
    string stack_name;
    if (env == NULL){
        stack_name = "default";
    } else {
        stack_name = env;
    }
    // Read stack, which is a comma separated list of component names,
    // into a vector of component names.
    _stack_list = getList("stacks", stack_name);
    if (stack_level >= static_cast<int>(_stack_list.size()) or stack_level < -1) {
        throw ConfigError("ConfigParser: stack level is out of bound");
    }
    if (stack_level == -1) {
        _default_section = "bridge";
    } else {
        _default_section = _stack_list[stack_level];
    }
}

vector<string> ConfigParser::getList(const std::string &section,
                                     const std::string &option) const {
    vector<string> ret;
    string s = get<string>(section, option);
    algorithm::split(ret, s, is_any_of("\t, "), token_compress_on);
    return ret;
}

string ConfigParser::getChildLibraryPath() const
{
    // Do we have a child?
    if (static_cast<int>(_stack_list.size()) <= stack_level+1) {
        throw ConfigNoChild("ConfigParser: " + getName() + " has no child!");
    }
    // Our child is our stack level plus one
    string child_name = _stack_list[stack_level+1];
    return get<string>(child_name, "impl");
}

} //namespace bohrium
<commit_msg>config: now handling dash in env var as underscore<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <string>
#include <algorithm>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/exceptions.hpp>
#include <boost/algorithm/string.hpp>
#include <cstdlib>

#include <bh_config_parser.hpp>

#ifdef _WIN32

#include <windows.h>
#include <dlfcn-win32.h>

#define HOME_INI_PATH "%APPDATA%\\bohrium\\config.ini"
#define SYSTEM_INI_PATH_1 "%PROGRAMFILES%\\bohrium\\config.ini"
#define SYSTEM_INI_PATH_2 "%PROGRAMFILES%\\bohrium\\config.ini"

//Nasty function renaming
#define snprintf _snprintf
#define strcasecmp _stricmp

#else

#include <dlfcn.h>
#include <limits.h>

#define HOME_INI_PATH "~/.bohrium/config.ini"
#define SYSTEM_INI_PATH_1 "/usr/local/etc/bohrium/config.ini"
#define SYSTEM_INI_PATH_2 "/usr/etc/bohrium/config.ini"

#endif

using namespace std;
using namespace boost;

namespace bohrium {

namespace {
// Path to the config file e.g. ~/.bohrium/config.ini
string get_config_path() {

    const char* homepath = HOME_INI_PATH;
    const char* syspath1 = SYSTEM_INI_PATH_1;
    const char* syspath2 = SYSTEM_INI_PATH_2;

    //
    // Find the configuration file
    //

    // Start by looking a path set via environment variable.
    const char *env = getenv("BH_CONFIG");
    if (env != NULL)
    {
        FILE *fp = fopen(env,"r");
        if( fp )
            fclose(fp);
        else
            env = NULL;//Did not exist.
    }

    // Then the home directory.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            homepath,
            _expand_buffer,
            MAX_PATH-1
        );

        if (result != 0)
        {
            homepath = _expand_buffer;
        }
#else
        char* h = getenv("HOME");
        if (h != NULL)
        {
            char _expand_buffer[PATH_MAX];
            snprintf(_expand_buffer, PATH_MAX, "%s/%s", h, homepath+1);
            homepath = _expand_buffer;
        }
#endif
        FILE *fp = fopen(homepath,"r");
        if( fp ) {
            env = homepath;
            fclose(fp);
        }
    }

    //And then system-wide.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            syspath1,
            _expand_buffer,
            MAX_PATH-1
        );

        if(result != 0)
        {
            syspath1 = _expand_buffer;
        }
#endif
        FILE *fp = fopen(syspath1,"r");
        if(fp)
        {
            env = syspath1;
            fclose(fp);
        }
    }

    //And then system-wide.
    if(env == NULL)
    {
#if _WIN32
        char _expand_buffer[MAX_PATH];
        DWORD result = ExpandEnvironmentStrings(
            syspath2,
            _expand_buffer,
            MAX_PATH-1
        );

        if(result != 0)
        {
            syspath2 = _expand_buffer;
        }
#endif
        FILE *fp = fopen(syspath2,"r");
        if(fp)
        {
            env = syspath2;
            fclose(fp);
        }
    }
    // We could not find the configuration file anywhere
    if(env == NULL)
    {
        fprintf(stderr, "Error: Bohrium could not find the config file.\n"
            " The search is:\n"
            "\t* The environment variable BH_CONFIG.\n"
            "\t* The home directory \"%s\".\n"
            "\t* The local directory \"%s\".\n"
            "\t* And system-wide \"%s\".\n", homepath, syspath1, syspath2);
        throw invalid_argument("No config file");
    }
    return string(env);
}

// Return section/option as an environment variable
// or the empty string if the environment variable wasn't found
string lookup_env(const string &section, const string &option) {
    string s = "BH_" + section + "_" + option;
    to_upper(s);
    std::replace(s.begin(), s.end(), '-', '_'); // replace all '-' to '_'
    std::replace(s.begin(), s.end(), ' ', '_'); // replace all ' ' to '_'
    const char *env = getenv(s.c_str());

    if (env == NULL) {
        return string();
    } else {
        return string(env);
    }
}

}// namespace unnamed

string ConfigParser::lookup(const string &section, const string &option) const {
    //Check environment variable
    string ret = lookup_env(section, option);
    if (not ret.empty())
        return ret;

    //Check config file
    ret = _config.get<string>(section + "." + option);

    //Remove quotes "" or '' and return
    if (ret.find_first_of("\"'") == 0 and ret.find_last_of("\"'") == ret.size()-1) {
        return ret.substr(1, ret.size()-2);
    } else {
        return ret;
    }
}

ConfigParser::ConfigParser(int stack_level) : file_path(get_config_path()),
                                              stack_level(stack_level) {

    // Load the bohrium configuration file
    property_tree::ini_parser::read_ini(file_path, _config);

    // Find the stack name specified by 'BH_STACK'
    const char *env = getenv("BH_STACK");
    string stack_name;
    if (env == NULL){
        stack_name = "default";
    } else {
        stack_name = env;
    }
    // Read stack, which is a comma separated list of component names,
    // into a vector of component names.
    _stack_list = getList("stacks", stack_name);
    if (stack_level >= static_cast<int>(_stack_list.size()) or stack_level < -1) {
        throw ConfigError("ConfigParser: stack level is out of bound");
    }
    if (stack_level == -1) {
        _default_section = "bridge";
    } else {
        _default_section = _stack_list[stack_level];
    }
}

vector<string> ConfigParser::getList(const std::string &section,
                                     const std::string &option) const {
    vector<string> ret;
    string s = get<string>(section, option);
    algorithm::split(ret, s, is_any_of("\t, "), token_compress_on);
    return ret;
}

string ConfigParser::getChildLibraryPath() const
{
    // Do we have a child?
    if (static_cast<int>(_stack_list.size()) <= stack_level+1) {
        throw ConfigNoChild("ConfigParser: " + getName() + " has no child!");
    }
    // Our child is our stack level plus one
    string child_name = _stack_list[stack_level+1];
    return get<string>(child_name, "impl");
}

} //namespace bohrium
<|endoftext|>