Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  WebGLTexelConversions.cpp   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "WebGLContext.h"
#include "WebGLTexelConversions.h"
#include "GLBlitHelper.h"

namespace mozilla {

using namespace WebGLTexelConversions;

namespace {

/** @class WebGLImageConverter
 *
 * This class is just a helper to implement WebGLContext::ConvertImage below.
 *
 * Design comments:
 *
 * WebGLContext::ConvertImage has to handle hundreds of format conversion paths.
 * It is important to minimize executable code size here. Instead of passing
 * around a large number of function parameters hundreds of times, we create a
 * WebGLImageConverter object once, storing these parameters, and then we call
 * the run() method on it.
 */

class WebGLImageConverter {
  const size_t mWidth, mHeight;
  const voidconst mSrcStart;
  voidconst mDstStart;
  const ptrdiff_t mSrcStride, mDstStride;
  bool mAlreadyRun;
  bool mSuccess;

  /*
   * Returns sizeof(texel)/sizeof(type). The point is that we will iterate over
   * texels with typed pointers and this value will tell us by how much we need
   * to increment these pointers to advance to the next texel.
   */

  template <WebGLTexelFormat Format>
  static size_t NumElementsPerTexelForFormat() {
    switch (Format) {
      case WebGLTexelFormat::A8:
      case WebGLTexelFormat::A16F:
      case WebGLTexelFormat::A32F:
      case WebGLTexelFormat::R8:
      case WebGLTexelFormat::R16F:
      case WebGLTexelFormat::R32F:
      case WebGLTexelFormat::RGB565:
      case WebGLTexelFormat::RGB11F11F10F:
      case WebGLTexelFormat::RGBA4444:
      case WebGLTexelFormat::RGBA5551:
        return 1;
      case WebGLTexelFormat::RA8:
      case WebGLTexelFormat::RA16F:
      case WebGLTexelFormat::RA32F:
      case WebGLTexelFormat::RG8:
      case WebGLTexelFormat::RG16F:
      case WebGLTexelFormat::RG32F:
        return 2;
      case WebGLTexelFormat::RGB8:
      case WebGLTexelFormat::RGB16F:
      case WebGLTexelFormat::RGB32F:
        return 3;
      case WebGLTexelFormat::RGBA8:
      case WebGLTexelFormat::RGBA16F:
      case WebGLTexelFormat::RGBA32F:
      case WebGLTexelFormat::BGRX8:
      case WebGLTexelFormat::BGRA8:
        return 4;
      default:
        MOZ_ASSERT(false"Unknown texel format. Coding mistake?");
        return 0;
    }
  }

  /*
   * This is the completely format-specific templatized conversion function,
   * that will be instantiated hundreds of times for all different combinations.
   * It is important to avoid generating useless code here. In particular, many
   * instantiations of this function template will never be called, so we try
   * to return immediately in these cases to allow the compiler to avoid
   * generating useless code.
   */

  template <WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat,
            WebGLTexelPremultiplicationOp PremultiplicationOp,
            dom::PredefinedColorSpace SrcColorSpace,
            dom::PredefinedColorSpace DstColorSpace>
  void run() {
    // check for never-called cases. We early-return to allow the compiler
    // to avoid generating this code. It would be tempting to abort() instead,
    // as returning early does leave the destination surface with uninitialized
    // data, but that would not allow the compiler to avoid generating this
    // code. So instead, we return early, so Success() will return false, and
    // the caller must check that and abort in that case. See
    // WebGLContext::ConvertImage.

    bool sameColorSpace = (SrcColorSpace == DstColorSpace);

    if (SrcFormat == DstFormat &&
        PremultiplicationOp == WebGLTexelPremultiplicationOp::None &&
        sameColorSpace) {
      // Should have used a fast exit path earlier, rather than entering this
      // function. we explicitly return here to allow the compiler to avoid
      // generating this code
      return;
    }

    // Only textures uploaded from DOM elements or ImageData can allow DstFormat
    // != SrcFormat. DOM elements can only give BGRA8, BGRX8, A8, RGB565
    // formats. See DOMElementToImageSurface. ImageData is always RGBA8. So all
    // other SrcFormat will always satisfy DstFormat==SrcFormat, so we can avoid
    // compiling the code for all the unreachable paths.
    const bool CanSrcFormatComeFromDOMElementOrImageData =
        SrcFormat == WebGLTexelFormat::BGRA8 ||
        SrcFormat == WebGLTexelFormat::BGRX8 ||
        SrcFormat == WebGLTexelFormat::A8 ||
        SrcFormat == WebGLTexelFormat::RGB565 ||
        SrcFormat == WebGLTexelFormat::RGBA8;
    if (!CanSrcFormatComeFromDOMElementOrImageData && SrcFormat != DstFormat) {
      return;
    }

    // Likewise, only textures uploaded from DOM elements or ImageData can
    // possibly have to be unpremultiplied.
    if (!CanSrcFormatComeFromDOMElementOrImageData &&
        PremultiplicationOp == WebGLTexelPremultiplicationOp::Unpremultiply) {
      return;
    }

    // there is no point in premultiplication/unpremultiplication
    // in the following cases:
    //  - the source format has no alpha
    //  - the source format has no color
    //  - the destination format has no color
    if (!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) {
      if (PremultiplicationOp != WebGLTexelPremultiplicationOp::None) {
        return;
      }
    }

    // end of early return cases.

    MOZ_ASSERT(!mAlreadyRun, "converter should be run only once!");
    mAlreadyRun = true;

    // gather some compile-time meta-data about the formats at hand.

    using SrcType = typename DataTypeForFormat<SrcFormat>::Type;
    using DstType = typename DataTypeForFormat<DstFormat>::Type;

    const WebGLTexelFormat IntermediateSrcFormat =
        IntermediateFormat<SrcFormat>::Value;
    const WebGLTexelFormat IntermediateDstFormat =
        IntermediateFormat<DstFormat>::Value;
    using IntermediateSrcType =
        typename DataTypeForFormat<IntermediateSrcFormat>::Type;
    using IntermediateDstType =
        typename DataTypeForFormat<IntermediateDstFormat>::Type;

    const size_t NumElementsPerSrcTexel =
        NumElementsPerTexelForFormat<SrcFormat>();
    const size_t NumElementsPerDstTexel =
        NumElementsPerTexelForFormat<DstFormat>();
    const size_t MaxElementsPerTexel = 4;
    MOZ_ASSERT(NumElementsPerSrcTexel <= MaxElementsPerTexel,
               "unhandled format");
    MOZ_ASSERT(NumElementsPerDstTexel <= MaxElementsPerTexel,
               "unhandled format");

    // we assume that the strides are multiples of the sizeof of respective
    // types. this assumption will allow us to iterate over src and dst images
    // using typed pointers, e.g. uint8_t* or uint16_t* or float*, instead of
    // untyped pointers. So this assumption allows us to write cleaner and safer
    // code, but it might not be true forever and if it eventually becomes
    // wrong, we'll have to revert to always iterating using uint8_t* pointers
    // regardless of the types at hand.
    MOZ_ASSERT(
        mSrcStride % sizeof(SrcType) == 0 && mDstStride % sizeof(DstType) == 0,
        "Unsupported: texture stride is not a multiple of sizeof(type)");
    const ptrdiff_t srcStrideInElements =
        mSrcStride / static_cast<ptrdiff_t>(sizeof(SrcType));
    const ptrdiff_t dstStrideInElements =
        mDstStride / static_cast<ptrdiff_t>(sizeof(DstType));
    // Pop quiz: What's `ptrdiff_t(-16) / sizeof(int32_t)`?
    // Did you guess +4611686018427387900?
    MOZ_ASSERT(bool(srcStrideInElements < 0) == bool(mSrcStride < 0));
    MOZ_ASSERT(bool(dstStrideInElements < 0) == bool(mDstStride < 0));

    const SrcType* srcRowStart = static_cast<const SrcType*>(mSrcStart);
    DstType* dstRowStart = static_cast<DstType*>(mDstStart);

    static auto inColorSpace2 = gfx::ToColorSpace2(SrcColorSpace);
    static auto outColorSpace2 = gfx::ToColorSpace2(DstColorSpace);

    auto inColorProfile = gl::GLBlitHelper::ToColorProfileDesc(inColorSpace2);
    auto outColorProfile = gl::GLBlitHelper::ToColorProfileDesc(outColorSpace2);

    const auto conversion = color::ColorProfileConversionDesc::From({
        .src = *inColorProfile,
        .dst = *outColorProfile,
    });

    // the loop performing the texture format conversion
    for (size_t i = 0; i < mHeight; ++i) {
      const SrcType* srcRowEnd = srcRowStart + mWidth * NumElementsPerSrcTexel;
      const SrcType* srcPtr = srcRowStart;
      DstType* dstPtr = dstRowStart;
      while (srcPtr != srcRowEnd) {
        // convert a single texel. We proceed in 4 steps: unpack the source
        // texel so the corresponding interchange format (e.g. unpack RGB565 to
        // RGBA8), do colorSpace conversion if necessary, convert the resulting
        // data type to the destination type (e.g. convert from RGBA8 to
        // RGBA32F), and finally pack the destination texel (e.g. pack RGBA32F
        // to RGB32F).
        IntermediateSrcType unpackedSrc[MaxElementsPerTexel];
        IntermediateDstType unpackedDst[MaxElementsPerTexel];

        // unpack a src texel to corresponding intermediate src format.
        // for example, unpack RGB565 to RGBA8
        unpack<SrcFormat>(srcPtr, unpackedSrc);

        if (!sameColorSpace) {
          // do colorSpace conversion, which leaves alpha untouched
          float srcAsFloat[MaxElementsPerTexel];
          convertType(unpackedSrc, srcAsFloat);
          auto inTexelVec =
              color::vec3({srcAsFloat[0], srcAsFloat[1], srcAsFloat[2]});
          auto outTexelVec = conversion.DstFromSrc(inTexelVec);
          srcAsFloat[0] = outTexelVec[0];
          srcAsFloat[1] = outTexelVec[1];
          srcAsFloat[2] = outTexelVec[2];
          convertType(srcAsFloat, unpackedSrc);
        }

        // convert the data type to the destination type, if needed.
        // for example, convert RGBA8 to RGBA32F
        convertType(unpackedSrc, unpackedDst);
        // pack the destination texel.
        // for example, pack RGBA32F to RGB32F
        pack<DstFormat, PremultiplicationOp>(unpackedDst, dstPtr);

        srcPtr += NumElementsPerSrcTexel;
        dstPtr += NumElementsPerDstTexel;
      }
      srcRowStart += srcStrideInElements;
      dstRowStart += dstStrideInElements;
    }

    mSuccess = true;
  }

  template <WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat,
            WebGLTexelPremultiplicationOp PremultiplicationOp,
            dom::PredefinedColorSpace SrcColorSpace>
  void run(dom::PredefinedColorSpace dstColorSpace) {
#define WEBGLIMAGECONVERTER_CASE_DSTCOLORSPACE(DstColorSpace)            \
  case DstColorSpace:                                                    \
    return run<SrcFormat, DstFormat, PremultiplicationOp, SrcColorSpace, \
               DstColorSpace>();

    switch (dstColorSpace) {
      WEBGLIMAGECONVERTER_CASE_DSTCOLORSPACE(dom::PredefinedColorSpace::Srgb)
      WEBGLIMAGECONVERTER_CASE_DSTCOLORSPACE(
          dom::PredefinedColorSpace::Display_p3)
      default:
        MOZ_ASSERT(false"unhandled case. Coding mistake?");
    }

#undef WEBGLIMAGECONVERTER_CASE_DSTCOLORSPACE
  }

  template <WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat,
            WebGLTexelPremultiplicationOp PremultiplicationOp>
  void run(dom::PredefinedColorSpace srcColorSpace,
           dom::PredefinedColorSpace dstColorSpace) {
#define WEBGLIMAGECONVERTER_CASE_SRCCOLORSPACE(SrcColorSpace)             \
  case SrcColorSpace:                                                     \
    return run<SrcFormat, DstFormat, PremultiplicationOp, SrcColorSpace>( \
        dstColorSpace);

    switch (srcColorSpace) {
      WEBGLIMAGECONVERTER_CASE_SRCCOLORSPACE(dom::PredefinedColorSpace::Srgb)
      WEBGLIMAGECONVERTER_CASE_SRCCOLORSPACE(
          dom::PredefinedColorSpace::Display_p3)
      default:
        MOZ_ASSERT(false"unhandled case. Coding mistake?");
    }

#undef WEBGLIMAGECONVERTER_CASE_SRCCOLORSPACE
  }

  template <WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat>
  void run(WebGLTexelPremultiplicationOp premultiplicationOp,
           dom::PredefinedColorSpace srcColorSpace,
           dom::PredefinedColorSpace dstColorSpace) {
#define WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(PremultiplicationOp) \
  case PremultiplicationOp:                                               \
    return run<SrcFormat, DstFormat, PremultiplicationOp>(srcColorSpace,  \
                                                          dstColorSpace);

    switch (premultiplicationOp) {
      WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(
          WebGLTexelPremultiplicationOp::None)
      WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(
          WebGLTexelPremultiplicationOp::Premultiply)
      WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(
          WebGLTexelPremultiplicationOp::Unpremultiply)
      default:
        MOZ_ASSERT(false"unhandled case. Coding mistake?");
    }

#undef WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP
  }

  template <WebGLTexelFormat SrcFormat>
  void run(WebGLTexelFormat dstFormat,
           WebGLTexelPremultiplicationOp premultiplicationOp,
           dom::PredefinedColorSpace srcColorSpace,
           dom::PredefinedColorSpace dstColorSpace) {
#define WEBGLIMAGECONVERTER_CASE_DSTFORMAT(DstFormat)                    \
  case DstFormat:                                                        \
    return run<SrcFormat, DstFormat>(premultiplicationOp, srcColorSpace, \
                                     dstColorSpace);

    switch (dstFormat) {
      // 1-channel formats
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
      // 2-channel formats
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RG32F)
      // 3-channel formats
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB11F11F10F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
      // 4-channel formats
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA16F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
      WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::BGRA8)

      default:
        MOZ_ASSERT(false"unhandled case. Coding mistake?");
    }

#undef WEBGLIMAGECONVERTER_CASE_DSTFORMAT
  }

 public:
  void run(WebGLTexelFormat srcFormat, WebGLTexelFormat dstFormat,
           WebGLTexelPremultiplicationOp premultiplicationOp,
           dom::PredefinedColorSpace srcColorSpace,
           dom::PredefinedColorSpace dstColorSpace) {
#define WEBGLIMAGECONVERTER_CASE_SRCFORMAT(SrcFormat)                    \
  case SrcFormat:                                                        \
    return run<SrcFormat>(dstFormat, premultiplicationOp, srcColorSpace, \
                          dstColorSpace);

    switch (srcFormat) {
      // 1-channel formats
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A16F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R16F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
      // 2-channel formats
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA16F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
      // 3-channel formats
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB16F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
      // 4-channel formats
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA16F)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
      // DOM element source formats
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8)
      WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)

      default:
        MOZ_ASSERT(false"unhandled case. Coding mistake?");
    }

#undef WEBGLIMAGECONVERTER_CASE_SRCFORMAT
  }

  WebGLImageConverter(size_t width, size_t height, const void* srcStart,
                      void* dstStart, ptrdiff_t srcStride, ptrdiff_t dstStride)
      : mWidth(width),
        mHeight(height),
        mSrcStart(srcStart),
        mDstStart(dstStart),
        mSrcStride(srcStride),
        mDstStride(dstStride),
        mAlreadyRun(false),
        mSuccess(false) {}

  bool Success() const { return mSuccess; }
};

}  // end anonymous namespace

bool ConvertImage(size_t width, size_t height, const void* srcBegin,
                  size_t srcStride, gl::OriginPos srcOrigin,
                  WebGLTexelFormat srcFormat, bool srcPremultiplied,
                  void* dstBegin, size_t dstStride, gl::OriginPos dstOrigin,
                  WebGLTexelFormat dstFormat, bool dstPremultiplied,
                  dom::PredefinedColorSpace srcColorSpace,
                  dom::PredefinedColorSpace dstColorSpace,
                  boolconst out_wasTrivial) {
  *out_wasTrivial = true;

  if (srcFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion ||
      dstFormat == WebGLTexelFormat::FormatNotSupportingAnyConversion) {
    return false;
  }

  if (!width || !height) return true;

  const bool shouldYFlip = (srcOrigin != dstOrigin);

  const bool canSkipPremult =
      (!HasAlpha(srcFormat) || !HasColor(srcFormat) || !HasColor(dstFormat));

  WebGLTexelPremultiplicationOp premultOp;
  if (canSkipPremult) {
    premultOp = WebGLTexelPremultiplicationOp::None;
  } else if (!srcPremultiplied && dstPremultiplied) {
    premultOp = WebGLTexelPremultiplicationOp::Premultiply;
  } else if (srcPremultiplied && !dstPremultiplied) {
    premultOp = WebGLTexelPremultiplicationOp::Unpremultiply;
  } else {
    premultOp = WebGLTexelPremultiplicationOp::None;
  }

  const uint8_t* srcItr = (const uint8_t*)srcBegin;
  const uint8_t* const srcEnd = srcItr + srcStride * height;
  uint8_t* dstItr = (uint8_t*)dstBegin;
  ptrdiff_t dstItrStride = dstStride;
  if (shouldYFlip) {
    dstItr = dstItr + dstStride * (height - 1);
    dstItrStride = -dstItrStride;
  }

  bool sameColorSpace = (srcColorSpace == dstColorSpace);

  if (srcFormat == dstFormat &&
      premultOp == WebGLTexelPremultiplicationOp::None && sameColorSpace) {
    // Fast exit path: we just have to memcpy all the rows.

    const auto bytesPerPixel = TexelBytesForFormat(srcFormat);
    const size_t bytesPerRow = bytesPerPixel * width;

    while (srcItr != srcEnd) {
      memcpy(dstItr, srcItr, bytesPerRow);
      srcItr += srcStride;
      dstItr += dstItrStride;
    }
    return true;
  }

  *out_wasTrivial = false;

  WebGLImageConverter converter(width, height, srcItr, dstItr, srcStride,
                                dstItrStride);
  converter.run(srcFormat, dstFormat, premultOp, srcColorSpace, dstColorSpace);
  if (!converter.Success()) {
    // the dst image may be left uninitialized, so we better not try to
    // continue even in release builds. This should never happen anyway,
    // and would be a bug in our code.
    MOZ_CRASH("programming mistake in WebGL texture conversions");
  }

  return true;
}

}  // end namespace mozilla

Messung V0.5
C=90 H=99 G=94

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge