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

#include "src/gpu/vk/GrVkAMDMemoryAllocator.h"

#include "include/gpu/vk/GrVkExtensions.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/vk/GrVkInterface.h"
#include "src/gpu/vk/GrVkMemory.h"
#include "src/gpu/vk/GrVkUtil.h"

#ifndef SK_USE_VMA
sk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
                                                        VkPhysicalDevice physicalDevice,
                                                        VkDevice device,
                                                        uint32_t physicalDeviceVersion,
                                                        const GrVkExtensions* extensions,
                                                        sk_sp<const GrVkInterface> interface,
                                                        const GrVkCaps* caps) {
    return nullptr;
}
#else

sk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
                                                        VkPhysicalDevice physicalDevice,
                                                        VkDevice device,
                                                        uint32_t physicalDeviceVersion,
                                                        const GrVkExtensions* extensions,
                                                        sk_sp<const GrVkInterface> interface,
                                                        const GrVkCaps* caps) {
#define GR_COPY_FUNCTION(NAME) functions.vk##NAME = interface->fFunctions.f##NAME
#define GR_COPY_FUNCTION_KHR(NAME) functions.vk##NAME##KHR = interface->fFunctions.f##NAME

    VmaVulkanFunctions functions;
    GR_COPY_FUNCTION(GetPhysicalDeviceProperties);
    GR_COPY_FUNCTION(GetPhysicalDeviceMemoryProperties);
    GR_COPY_FUNCTION(AllocateMemory);
    GR_COPY_FUNCTION(FreeMemory);
    GR_COPY_FUNCTION(MapMemory);
    GR_COPY_FUNCTION(UnmapMemory);
    GR_COPY_FUNCTION(FlushMappedMemoryRanges);
    GR_COPY_FUNCTION(InvalidateMappedMemoryRanges);
    GR_COPY_FUNCTION(BindBufferMemory);
    GR_COPY_FUNCTION(BindImageMemory);
    GR_COPY_FUNCTION(GetBufferMemoryRequirements);
    GR_COPY_FUNCTION(GetImageMemoryRequirements);
    GR_COPY_FUNCTION(CreateBuffer);
    GR_COPY_FUNCTION(DestroyBuffer);
    GR_COPY_FUNCTION(CreateImage);
    GR_COPY_FUNCTION(DestroyImage);
    GR_COPY_FUNCTION(CmdCopyBuffer);
    GR_COPY_FUNCTION_KHR(GetBufferMemoryRequirements2);
    GR_COPY_FUNCTION_KHR(GetImageMemoryRequirements2);
    GR_COPY_FUNCTION_KHR(BindBufferMemory2);
    GR_COPY_FUNCTION_KHR(BindImageMemory2);
    GR_COPY_FUNCTION_KHR(GetPhysicalDeviceMemoryProperties2);

    VmaAllocatorCreateInfo info;
    info.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
        (extensions->hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
         extensions->hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1))) {
        info.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
    }

    info.physicalDevice = physicalDevice;
    info.device = device;
    // 4MB was picked for the size here by looking at memory usage of Android apps and runs of DM.
    // It seems to be a good compromise of not wasting unused allocated space and not making too
    // many small allocations. The AMD allocator will start making blocks at 1/8 the max size and
    // builds up block size as needed before capping at the max set here.
    info.preferredLargeHeapBlockSize = 4*1024*1024;
    info.pAllocationCallbacks = nullptr;
    info.pDeviceMemoryCallbacks = nullptr;
    info.frameInUseCount = 0;
    info.pHeapSizeLimit = nullptr;
    info.pVulkanFunctions = &functions;
    info.pRecordSettings = nullptr;
    info.instance = instance;
    info.vulkanApiVersion = physicalDeviceVersion;

    VmaAllocator allocator;
    vmaCreateAllocator(&info, &allocator);

    return sk_sp<GrVkAMDMemoryAllocator>(new GrVkAMDMemoryAllocator(
            allocator, std::move(interface), caps->mustUseCoherentHostVisibleMemory()));
}

GrVkAMDMemoryAllocator::GrVkAMDMemoryAllocator(VmaAllocator allocator,
                                               sk_sp<const GrVkInterface> interface,
                                               bool mustUseCoherentHostVisibleMemory)
        : fAllocator(allocator)
        , fInterface(std::move(interface))
        , fMustUseCoherentHostVisibleMemory(mustUseCoherentHostVisibleMemory) {}

GrVkAMDMemoryAllocator::~GrVkAMDMemoryAllocator() {
    vmaDestroyAllocator(fAllocator);
    fAllocator = VK_NULL_HANDLE;
}

VkResult GrVkAMDMemoryAllocator::allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
                                                     GrVkBackendMemory* backendMemory) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    VmaAllocationCreateInfo info;
    info.flags = 0;
    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
    info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    info.preferredFlags = 0;
    info.memoryTypeBits = 0;
    info.pool = VK_NULL_HANDLE;
    info.pUserData = nullptr;

    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
    }

    if (AllocationPropertyFlags::kLazyAllocation & flags) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
    }

    if (AllocationPropertyFlags::kProtected & flags) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
    }

    VmaAllocation allocation;
    VkResult result = vmaAllocateMemoryForImage(fAllocator, image, &info, &allocation, nullptr);
    if (VK_SUCCESS == result) {
        *backendMemory = (GrVkBackendMemory)allocation;
    }
    return result;
}

VkResult GrVkAMDMemoryAllocator::allocateBufferMemory(VkBuffer buffer, BufferUsage usage,
                                                      AllocationPropertyFlags flags,
                                                      GrVkBackendMemory* backendMemory) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    VmaAllocationCreateInfo info;
    info.flags = 0;
    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
    info.memoryTypeBits = 0;
    info.pool = VK_NULL_HANDLE;
    info.pUserData = nullptr;

    switch (usage) {
        case BufferUsage::kGpuOnly:
            info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
            info.preferredFlags = 0;
            break;
        case BufferUsage::kCpuWritesGpuReads:
            // When doing cpu writes and gpu reads the general rule of thumb is to use coherent
            // memory. Though this depends on the fact that we are not doing any cpu reads and the
            // cpu writes are sequential. For sparse writes we'd want cpu cached memory, however we
            // don't do these types of writes in Skia.
            //
            // TODO: In the future there may be times where specific types of memory could benefit
            // from a coherent and cached memory. Typically these allow for the gpu to read cpu
            // writes from the cache without needing to flush the writes throughout the cache. The
            // reverse is not true and GPU writes tend to invalidate the cache regardless. Also
            // these gpu cache read access are typically lower bandwidth than non-cached memory.
            // For now Skia doesn't really have a need or want of this type of memory. But if we
            // ever do we could pass in an AllocationPropertyFlag that requests the cached property.
            info.requiredFlags =
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
            info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
            break;
        case BufferUsage::kTransfersFromCpuToGpu:
            info.requiredFlags =
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
            break;
        case BufferUsage::kTransfersFromGpuToCpu:
            info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
            info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
            break;
    }

    if (fMustUseCoherentHostVisibleMemory &&
        (info.requiredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    }

    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
    }

    if ((AllocationPropertyFlags::kLazyAllocation & flags) && BufferUsage::kGpuOnly == usage) {
        info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
    }

    if (AllocationPropertyFlags::kPersistentlyMapped & flags) {
        SkASSERT(BufferUsage::kGpuOnly != usage);
        info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
    }

    VmaAllocation allocation;
    VkResult result = vmaAllocateMemoryForBuffer(fAllocator, buffer, &info, &allocation, nullptr);
    if (VK_SUCCESS == result) {
        *backendMemory = (GrVkBackendMemory)allocation;
    }

    return result;
}

void GrVkAMDMemoryAllocator::freeMemory(const GrVkBackendMemory& memoryHandle) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    vmaFreeMemory(fAllocator, allocation);
}

void GrVkAMDMemoryAllocator::getAllocInfo(const GrVkBackendMemory& memoryHandle,
                                          GrVkAlloc* alloc) const {
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    VmaAllocationInfo vmaInfo;
    vmaGetAllocationInfo(fAllocator, allocation, &vmaInfo);

    VkMemoryPropertyFlags memFlags;
    vmaGetMemoryTypeProperties(fAllocator, vmaInfo.memoryType, &memFlags);

    uint32_t flags = 0;
    if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & memFlags) {
        flags |= GrVkAlloc::kMappable_Flag;
    }
    if (!SkToBool(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & memFlags)) {
        flags |= GrVkAlloc::kNoncoherent_Flag;
    }
    if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & memFlags) {
        flags |= GrVkAlloc::kLazilyAllocated_Flag;
    }

    alloc->fMemory        = vmaInfo.deviceMemory;
    alloc->fOffset        = vmaInfo.offset;
    alloc->fSize          = vmaInfo.size;
    alloc->fFlags         = flags;
    alloc->fBackendMemory = memoryHandle;
}

VkResult GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle, void** data) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaMapMemory(fAllocator, allocation, data);
}

void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    vmaUnmapMemory(fAllocator, allocation);
}

VkResult GrVkAMDMemoryAllocator::flushMemory(const GrVkBackendMemory& memoryHandle,
                                             VkDeviceSize offset, VkDeviceSize size) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaFlushAllocation(fAllocator, allocation, offset, size);
}

VkResult GrVkAMDMemoryAllocator::invalidateMemory(const GrVkBackendMemory& memoryHandle,
                                                  VkDeviceSize offset, VkDeviceSize size) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaInvalidateAllocation(fAllocator, allocation, offset, size);
}

uint64_t GrVkAMDMemoryAllocator::totalUsedMemory() const {
    VmaStats stats;
    vmaCalculateStats(fAllocator, &stats);
    return stats.total.usedBytes;
}

uint64_t GrVkAMDMemoryAllocator::totalAllocatedMemory() const {
    VmaStats stats;
    vmaCalculateStats(fAllocator, &stats);
    return stats.total.usedBytes + stats.total.unusedBytes;
}

#endif // SK_USE_VMA
<commit_msg>Fix MSAN unitialized memory in vulkan memory allocator.<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/vk/GrVkAMDMemoryAllocator.h"

#include "include/gpu/vk/GrVkExtensions.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/vk/GrVkInterface.h"
#include "src/gpu/vk/GrVkMemory.h"
#include "src/gpu/vk/GrVkUtil.h"

#ifndef SK_USE_VMA
sk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
                                                        VkPhysicalDevice physicalDevice,
                                                        VkDevice device,
                                                        uint32_t physicalDeviceVersion,
                                                        const GrVkExtensions* extensions,
                                                        sk_sp<const GrVkInterface> interface,
                                                        const GrVkCaps* caps) {
    return nullptr;
}
#else

sk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
                                                        VkPhysicalDevice physicalDevice,
                                                        VkDevice device,
                                                        uint32_t physicalDeviceVersion,
                                                        const GrVkExtensions* extensions,
                                                        sk_sp<const GrVkInterface> interface,
                                                        const GrVkCaps* caps) {
#define GR_COPY_FUNCTION(NAME) functions.vk##NAME = interface->fFunctions.f##NAME
#define GR_COPY_FUNCTION_KHR(NAME) functions.vk##NAME##KHR = interface->fFunctions.f##NAME

    VmaVulkanFunctions functions;
    GR_COPY_FUNCTION(GetPhysicalDeviceProperties);
    GR_COPY_FUNCTION(GetPhysicalDeviceMemoryProperties);
    GR_COPY_FUNCTION(AllocateMemory);
    GR_COPY_FUNCTION(FreeMemory);
    GR_COPY_FUNCTION(MapMemory);
    GR_COPY_FUNCTION(UnmapMemory);
    GR_COPY_FUNCTION(FlushMappedMemoryRanges);
    GR_COPY_FUNCTION(InvalidateMappedMemoryRanges);
    GR_COPY_FUNCTION(BindBufferMemory);
    GR_COPY_FUNCTION(BindImageMemory);
    GR_COPY_FUNCTION(GetBufferMemoryRequirements);
    GR_COPY_FUNCTION(GetImageMemoryRequirements);
    GR_COPY_FUNCTION(CreateBuffer);
    GR_COPY_FUNCTION(DestroyBuffer);
    GR_COPY_FUNCTION(CreateImage);
    GR_COPY_FUNCTION(DestroyImage);
    GR_COPY_FUNCTION(CmdCopyBuffer);
    GR_COPY_FUNCTION_KHR(GetBufferMemoryRequirements2);
    GR_COPY_FUNCTION_KHR(GetImageMemoryRequirements2);
    GR_COPY_FUNCTION_KHR(BindBufferMemory2);
    GR_COPY_FUNCTION_KHR(BindImageMemory2);
    GR_COPY_FUNCTION_KHR(GetPhysicalDeviceMemoryProperties2);

    VmaAllocatorCreateInfo info;
    info.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
        (extensions->hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
         extensions->hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1))) {
        info.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
    }

    info.physicalDevice = physicalDevice;
    info.device = device;
    // 4MB was picked for the size here by looking at memory usage of Android apps and runs of DM.
    // It seems to be a good compromise of not wasting unused allocated space and not making too
    // many small allocations. The AMD allocator will start making blocks at 1/8 the max size and
    // builds up block size as needed before capping at the max set here.
    info.preferredLargeHeapBlockSize = 4*1024*1024;
    info.pAllocationCallbacks = nullptr;
    info.pDeviceMemoryCallbacks = nullptr;
    info.frameInUseCount = 0;
    info.pHeapSizeLimit = nullptr;
    info.pVulkanFunctions = &functions;
    info.pRecordSettings = nullptr;
    info.instance = instance;
    info.vulkanApiVersion = physicalDeviceVersion;

    VmaAllocator allocator;
    vmaCreateAllocator(&info, &allocator);

    return sk_sp<GrVkAMDMemoryAllocator>(new GrVkAMDMemoryAllocator(
            allocator, std::move(interface), caps->mustUseCoherentHostVisibleMemory()));
}

GrVkAMDMemoryAllocator::GrVkAMDMemoryAllocator(VmaAllocator allocator,
                                               sk_sp<const GrVkInterface> interface,
                                               bool mustUseCoherentHostVisibleMemory)
        : fAllocator(allocator)
        , fInterface(std::move(interface))
        , fMustUseCoherentHostVisibleMemory(mustUseCoherentHostVisibleMemory) {}

GrVkAMDMemoryAllocator::~GrVkAMDMemoryAllocator() {
    vmaDestroyAllocator(fAllocator);
    fAllocator = VK_NULL_HANDLE;
}

VkResult GrVkAMDMemoryAllocator::allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
                                                     GrVkBackendMemory* backendMemory) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    VmaAllocationCreateInfo info;
    info.flags = 0;
    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
    info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
    info.preferredFlags = 0;
    info.memoryTypeBits = 0;
    info.pool = VK_NULL_HANDLE;
    info.pUserData = nullptr;

    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
    }

    if (AllocationPropertyFlags::kLazyAllocation & flags) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
    }

    if (AllocationPropertyFlags::kProtected & flags) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
    }

    VmaAllocation allocation;
    VkResult result = vmaAllocateMemoryForImage(fAllocator, image, &info, &allocation, nullptr);
    if (VK_SUCCESS == result) {
        *backendMemory = (GrVkBackendMemory)allocation;
    }
    return result;
}

VkResult GrVkAMDMemoryAllocator::allocateBufferMemory(VkBuffer buffer, BufferUsage usage,
                                                      AllocationPropertyFlags flags,
                                                      GrVkBackendMemory* backendMemory) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    VmaAllocationCreateInfo info;
    info.flags = 0;
    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
    info.memoryTypeBits = 0;
    info.pool = VK_NULL_HANDLE;
    info.pUserData = nullptr;

    switch (usage) {
        case BufferUsage::kGpuOnly:
            info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
            info.preferredFlags = 0;
            break;
        case BufferUsage::kCpuWritesGpuReads:
            // When doing cpu writes and gpu reads the general rule of thumb is to use coherent
            // memory. Though this depends on the fact that we are not doing any cpu reads and the
            // cpu writes are sequential. For sparse writes we'd want cpu cached memory, however we
            // don't do these types of writes in Skia.
            //
            // TODO: In the future there may be times where specific types of memory could benefit
            // from a coherent and cached memory. Typically these allow for the gpu to read cpu
            // writes from the cache without needing to flush the writes throughout the cache. The
            // reverse is not true and GPU writes tend to invalidate the cache regardless. Also
            // these gpu cache read access are typically lower bandwidth than non-cached memory.
            // For now Skia doesn't really have a need or want of this type of memory. But if we
            // ever do we could pass in an AllocationPropertyFlag that requests the cached property.
            info.requiredFlags =
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
            info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
            break;
        case BufferUsage::kTransfersFromCpuToGpu:
            info.requiredFlags =
                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
            info.preferredFlags = 0;
            break;
        case BufferUsage::kTransfersFromGpuToCpu:
            info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
            info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
            break;
    }

    if (fMustUseCoherentHostVisibleMemory &&
        (info.requiredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
        info.requiredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    }

    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
    }

    if ((AllocationPropertyFlags::kLazyAllocation & flags) && BufferUsage::kGpuOnly == usage) {
        info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
    }

    if (AllocationPropertyFlags::kPersistentlyMapped & flags) {
        SkASSERT(BufferUsage::kGpuOnly != usage);
        info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
    }

    VmaAllocation allocation;
    VkResult result = vmaAllocateMemoryForBuffer(fAllocator, buffer, &info, &allocation, nullptr);
    if (VK_SUCCESS == result) {
        *backendMemory = (GrVkBackendMemory)allocation;
    }

    return result;
}

void GrVkAMDMemoryAllocator::freeMemory(const GrVkBackendMemory& memoryHandle) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    vmaFreeMemory(fAllocator, allocation);
}

void GrVkAMDMemoryAllocator::getAllocInfo(const GrVkBackendMemory& memoryHandle,
                                          GrVkAlloc* alloc) const {
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    VmaAllocationInfo vmaInfo;
    vmaGetAllocationInfo(fAllocator, allocation, &vmaInfo);

    VkMemoryPropertyFlags memFlags;
    vmaGetMemoryTypeProperties(fAllocator, vmaInfo.memoryType, &memFlags);

    uint32_t flags = 0;
    if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & memFlags) {
        flags |= GrVkAlloc::kMappable_Flag;
    }
    if (!SkToBool(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & memFlags)) {
        flags |= GrVkAlloc::kNoncoherent_Flag;
    }
    if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & memFlags) {
        flags |= GrVkAlloc::kLazilyAllocated_Flag;
    }

    alloc->fMemory        = vmaInfo.deviceMemory;
    alloc->fOffset        = vmaInfo.offset;
    alloc->fSize          = vmaInfo.size;
    alloc->fFlags         = flags;
    alloc->fBackendMemory = memoryHandle;
}

VkResult GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle, void** data) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaMapMemory(fAllocator, allocation, data);
}

void GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    vmaUnmapMemory(fAllocator, allocation);
}

VkResult GrVkAMDMemoryAllocator::flushMemory(const GrVkBackendMemory& memoryHandle,
                                             VkDeviceSize offset, VkDeviceSize size) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaFlushAllocation(fAllocator, allocation, offset, size);
}

VkResult GrVkAMDMemoryAllocator::invalidateMemory(const GrVkBackendMemory& memoryHandle,
                                                  VkDeviceSize offset, VkDeviceSize size) {
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
    return vmaInvalidateAllocation(fAllocator, allocation, offset, size);
}

uint64_t GrVkAMDMemoryAllocator::totalUsedMemory() const {
    VmaStats stats;
    vmaCalculateStats(fAllocator, &stats);
    return stats.total.usedBytes;
}

uint64_t GrVkAMDMemoryAllocator::totalAllocatedMemory() const {
    VmaStats stats;
    vmaCalculateStats(fAllocator, &stats);
    return stats.total.usedBytes + stats.total.unusedBytes;
}

#endif // SK_USE_VMA
<|endoftext|>


<commit_before>//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Copyright (C) 2008-2010 The PECOS Development Team
//
// Please see http://pecos.ices.utexas.edu for more information.
//
// This file is part of GRINS.
//
// GRINS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GRINS 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 General Public License
// along with GRINS.  If not, see <http://www.gnu.org/licenses/>.
//
//--------------------------------------------------------------------------
//
// Driver code for GRINS (FEM solver).
//
// $Id$
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

#include "grins_solver.h"

#include <iostream>

int main(int argc, char* argv[]) {

  // Check command line count.
  if( argc != 2 )
    {
      std::cout << "Error: Must specify libMesh input file." << std::endl;
      exit(1);
    }

  // Initialize libMesh library.
  LibMeshInit libmesh_init(argc, argv);

   // Create solver object.
  std::string dummy = "TODO: Delete me when agreed on constructor arguments.";
  GRINS::GRINSSolver solver( dummy );

  { // Artificial block to destroy objects associated with reading the input once we've read it in.

    // libMesh input file should be first argument
    std::string libMesh_input = argv[1];

    // Create our GetPot object. TODO: Finalize decision of GRVY vs. GetPot input.
    GetPot libMesh_inputfile( libMesh_input );

    solver.read_input_options( libMesh_inputfile );
  } //Should be done reading input, so we kill the GetPot object.

  return 0;
}
<commit_msg>[grins/code/trunk]: added GRVY timer in generic dirver. Related to #1219.<commit_after>//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// Copyright (C) 2008-2010 The PECOS Development Team
//
// Please see http://pecos.ices.utexas.edu for more information.
//
// This file is part of GRINS.
//
// GRINS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GRINS 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 General Public License
// along with GRINS.  If not, see <http://www.gnu.org/licenses/>.
//
//--------------------------------------------------------------------------
//
// Driver code for GRINS (FEM solver).
//
// $Id$
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

#include "grins_solver.h"

#include <iostream>
#include "grvy.h"

int main(int argc, char* argv[]) {

  // Check command line count.
  if( argc != 2 )
    {
      std::cout << "Error: Must specify libMesh input file." << std::endl;
      exit(1);
    }

  GRVY::GRVY_Timer_Class grvy_timer;
  grvy_timer.Init("GRVY Timer in GRINS Driver");

  // Initialize libMesh library.
  LibMeshInit libmesh_init(argc, argv);

   // Create solver object.
  std::string dummy = "TODO: Delete me when agreed on constructor arguments.";
  GRINS::GRINSSolver solver( dummy );

  grvy_timer.BeginTimer("Generic Driver - input reading block timing");
  { // Artificial block to destroy objects associated with reading the input once we've read it in.

    // libMesh input file should be first argument
    std::string libMesh_input = argv[1];

    // Create our GetPot object. TODO: Finalize decision of GRVY vs. GetPot input.
    GetPot libMesh_inputfile( libMesh_input );

    solver.read_input_options( libMesh_inputfile );
  } //Should be done reading input, so we kill the GetPot object.

  grvy_timer.EndTimer("Generic Driver - input reading block timing");

  grvy_timer.Finalize();
  grvy_timer.Summarize();

  return 0;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// 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 the copyright holder 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 HOLDER 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 <QComboBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QString>
#include <QToolButton>
#include <QVBoxLayout>
#include <iomanip>
#include <sstream>
#include <string>

#include "gui/gui.h"
#include "highlightGroupDialog.h"
#include "selectHighlightWindow.h"

namespace gui {

static QString getBBoxString(odb::Rect& bbox, odb::dbDatabase* db)
{
  double to_microns = db->getChip()->getBlock()->getDbUnitsPerMicron();
  std::stringstream ss;
  ss << std::fixed << std::setprecision(5) << "(";
  ss << bbox.xMin() / to_microns << ",";
  ss << bbox.yMin() / to_microns << "), (";
  ss << bbox.xMax() / to_microns << ",";
  ss << bbox.yMax() / to_microns << ")";
  return QString::fromStdString(ss.str());
}

SelectionModel::SelectionModel(const SelectionSet& objs)
    : db_(nullptr), objs_(objs)
{
}

void SelectionModel::populateModel()
{
  beginResetModel();
  table_data_.clear();
  table_data_.reserve(objs_.size());
  for (auto& obj : objs_) {
    table_data_.push_back(&obj);
  }
  endResetModel();
}

int SelectionModel::rowCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return objs_.size();
}

int SelectionModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return 3;
}

QVariant SelectionModel::data(const QModelIndex& index, int role) const
{
  if (!index.isValid() || role != Qt::DisplayRole) {
    return QVariant();
  }
  unsigned int row_index = index.row();
  if (row_index > table_data_.size())
    return QVariant();
  const std::string obj_name = table_data_[row_index]->getName();
  const std::string obj_type = table_data_[row_index]->getTypeName();
  if (index.column() == 0) {
    return QString::fromStdString(obj_name);
  } else if (index.column() == 1) {
    return QString::fromStdString(obj_type);
  } else if (index.column() == 2) {
    odb::Rect bbox;
    bool valid = table_data_[row_index]->getBBox(bbox);
    return valid ? getBBoxString(bbox, db_) : "<none>";
  }
  return QVariant();
}

QVariant SelectionModel::headerData(int section,
                                    Qt::Orientation orientation,
                                    int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
    if (section == 0) {
      return QString("Object");
    } else if (section == 1) {
      return QString("Type");
    } else if (section == 2) {
      return QString("Bounds");
    }
  }
  return QVariant();
}

HighlightModel::HighlightModel(const HighlightSet& objs)
    : db_(nullptr), objs_(objs)
{
}

void HighlightModel::populateModel()
{
  beginResetModel();
  table_data_.clear();
  table_data_.reserve(objs_.size());
  int highlight_group = 0;
  for (auto& highlight_objs : objs_) {
    for (auto& obj : highlight_objs) {
      table_data_.push_back(std::make_pair(highlight_group, &obj));
    }
    ++highlight_group;
  }
  endResetModel();
}

int HighlightModel::rowCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return table_data_.size();
}

int HighlightModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return 4;
}

QVariant HighlightModel::data(const QModelIndex& index, int role) const
{
  if (!index.isValid()
      || (role != Qt::DisplayRole && role != Qt::EditRole
          && role != Qt::BackgroundRole)) {
    return QVariant();
  }
  if (role == Qt::BackgroundRole && index.column() != 3)
    return QVariant();
  else if (role == Qt::BackgroundRole && index.column() == 3) {
    auto highlight_color
        = Painter::highlightColors[table_data_[index.row()].first];
    return QColor(highlight_color.r, highlight_color.g, highlight_color.b, 100);
  }
  unsigned int row_index = index.row();
  if (row_index > table_data_.size())
    return QVariant();
  std::string obj_name = table_data_[row_index].second->getName();
  std::string obj_type("");
  if (obj_name.rfind("Net: ", 0) == 0) {
    obj_name = obj_name.substr(5);
    obj_type = "Net";
  } else if (obj_name.rfind("Inst: ", 0) == 0) {
    obj_name = obj_name.substr(6);
    obj_type = "Instance";
  }
  if (index.column() == 0) {
    return QString::fromStdString(obj_name);
  } else if (index.column() == 1) {
    return QString::fromStdString(obj_type);
  } else if (index.column() == 2) {
    odb::Rect bbox;
    bool valid = table_data_[row_index].second->getBBox(bbox);
    return valid ? getBBoxString(bbox, db_) : "<none>";
  } else if (index.column() == 3) {
    return QString("Group ")
           + QString::number(table_data_[row_index].first + 1);
  }
  return QVariant();
}

QVariant HighlightModel::headerData(int section,
                                    Qt::Orientation orientation,
                                    int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
    if (section == 0) {
      return QString("Object");
    } else if (section == 1) {
      return QString("Type");
    } else if (section == 2) {
      return QString("Bounds");
    } else if (section == 3) {
      return QString("Highlight Group");
    }
  }
  return QVariant();
}

int HighlightModel::highlightGroup(const QModelIndex& index) const
{
  int row_index = index.row();
  return table_data_[row_index].first;
}

bool HighlightModel::setData(const QModelIndex& index,
                             const QVariant& value,
                             int role)
{
  return false;
}

HighlightGroupDelegate::HighlightGroupDelegate(QObject* parent)
    : QStyledItemDelegate(parent)
{
  items_.push_back("Group 1");
  items_.push_back("Group 2");
  items_.push_back("Group 3");
  items_.push_back("Group 4");
  items_.push_back("Group 5");
  items_.push_back("Group 6");
  items_.push_back("Group 7");
  items_.push_back("Group 8");
}

QWidget* HighlightGroupDelegate::createEditor(
    QWidget* parent,
    const QStyleOptionViewItem& /* option */,
    const QModelIndex& index) const
{
  QComboBox* editor = new QComboBox(parent);
  for (unsigned int i = 0; i < items_.size(); ++i) {
    editor->addItem(items_[i].c_str());
  }
  editor->setFrame(true);
  editor->setEditable(true);
  return editor;
}

void HighlightGroupDelegate::setEditorData(QWidget* editor,
                                           const QModelIndex& index) const
{
  QString value = index.model()->data(index, Qt::EditRole).toString();
  QComboBox* combo_box = static_cast<QComboBox*>(editor);
  combo_box->setCurrentText(value);
}

void HighlightGroupDelegate::setModelData(QWidget* editor,
                                          QAbstractItemModel* model,
                                          const QModelIndex& index) const
{
  QComboBox* combo_box = static_cast<QComboBox*>(editor);
  model->setData(index, combo_box->currentIndex(), Qt::EditRole);
}

void HighlightGroupDelegate::updateEditorGeometry(
    QWidget* editor,
    const QStyleOptionViewItem& option,
    const QModelIndex& /* index */) const
{
  editor->setGeometry(option.rect);
}

void HighlightGroupDelegate::paint(QPainter* painter,
                                   const QStyleOptionViewItem& option,
                                   const QModelIndex& index) const
{
  QStyleOptionViewItem my_option = option;

  QString text = index.model()->data(index, Qt::EditRole).toString();
  my_option.text = text;
  QApplication::style()->drawControl(
      QStyle::CE_ItemViewItem, &my_option, painter);
}

SelectHighlightWindow::SelectHighlightWindow(const SelectionSet& sel_set,
                                             const HighlightSet& hlt_set,
                                             QWidget* parent)
    : QDockWidget(parent),
      ui(new Ui::SelectHighlightWidget),
      selection_model_(sel_set),
      highlight_model_(hlt_set),
      select_context_menu_(new QMenu(this)),
      highlight_context_menu_(new QMenu(this))
{
  ui->setupUi(this);

  QSortFilterProxyModel* sel_filter_proxy = new QSortFilterProxyModel(this);
  sel_filter_proxy->setSourceModel(&selection_model_);

  QSortFilterProxyModel* hlt_filter_proxy = new QSortFilterProxyModel(this);
  hlt_filter_proxy->setSourceModel(&highlight_model_);

  ui->selTableView->setModel(sel_filter_proxy);
  ui->hltTableView->setModel(hlt_filter_proxy);

  connect(ui->findEditInSel, &QLineEdit::returnPressed, this, [this]() {
    this->ui->selTableView->keyboardSearch(ui->findEditInSel->text());
  });
  connect(ui->findEditInHlt, &QLineEdit::returnPressed, this, [this]() {
    this->ui->hltTableView->keyboardSearch(ui->findEditInSel->text());
  });

  connect(ui->selTableView,
          SIGNAL(customContextMenuRequested(QPoint)),
          this,
          SLOT(showSelectCustomMenu(QPoint)));
  connect(ui->hltTableView,
          SIGNAL(customContextMenuRequested(QPoint)),
          this,
          SLOT(showHighlightCustomMenu(QPoint)));
  ui->selTableView->horizontalHeader()->setSectionResizeMode(
      QHeaderView::Stretch);
  ui->hltTableView->horizontalHeader()->setSectionResizeMode(
      QHeaderView::Stretch);

  QAction* remove_sel_item_act = select_context_menu_->addAction("De-Select");
  QAction* remove_all_sel_items = select_context_menu_->addAction("Clear All");
  QAction* highlight_sel_item_act
      = select_context_menu_->addAction("Highlight");
  select_context_menu_->addSeparator();
  QAction* show_sel_item_act
      = select_context_menu_->addAction("Zoom In Layout");

  connect(
      remove_sel_item_act, SIGNAL(triggered()), this, SLOT(deselectItems()));
  connect(remove_all_sel_items, &QAction::triggered, this, [this]() {
    emit clearAllSelections();
  });
  connect(highlight_sel_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(highlightSelectedItems()));
  connect(show_sel_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(zoomInSelectedItems()));

  QAction* remove_hlt_item_act
      = highlight_context_menu_->addAction("De-Highlight");
  QAction* remove_all_hlt_items
      = highlight_context_menu_->addAction("Clear All");
  highlight_context_menu_->addSeparator();
  QAction* show_hlt_item_act
      = highlight_context_menu_->addAction("Zoom In Layout");

  connect(
      remove_hlt_item_act, SIGNAL(triggered()), this, SLOT(dehighlightItems()));
  connect(remove_all_hlt_items, &QAction::triggered, this, [this]() {
    emit clearAllHighlights();
  });
  connect(show_hlt_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(zoomInHighlightedItems()));

  ui->selTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
  ui->hltTableView->setSelectionBehavior(QAbstractItemView::SelectRows);

  ui->tabWidget->setCurrentIndex(0);
}

SelectHighlightWindow::~SelectHighlightWindow()
{
}

void SelectHighlightWindow::updateSelectionModel()
{
  selection_model_.populateModel();
}

void SelectHighlightWindow::updateHighlightModel()
{
  highlight_model_.populateModel();
}

void SelectHighlightWindow::showSelectCustomMenu(QPoint pos)
{
  select_context_menu_->popup(ui->selTableView->viewport()->mapToGlobal(pos));
}

void SelectHighlightWindow::showHighlightCustomMenu(QPoint pos)
{
  highlight_context_menu_->popup(
      ui->hltTableView->viewport()->mapToGlobal(pos));
}

void SelectHighlightWindow::deselectItems()
{
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> desel_items;
  for (auto& sel_item : sel_indices) {
    desel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit clearSelectedItems(desel_items);
}
void SelectHighlightWindow::highlightSelectedItems()
{
  HighlightGroupDialog dlg;
  dlg.exec();
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> sel_items;
  for (auto& sel_item : sel_indices) {
    sel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit highlightSelectedItemsSig(sel_items, dlg.getSelectedHighlightGroup());
}

void SelectHighlightWindow::zoomInSelectedItems()
{
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> desel_items;
  for (auto& sel_item : sel_indices) {
    desel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit zoomInToItems(desel_items);
}

void SelectHighlightWindow::dehighlightItems()
{
  auto sel_indices = ui->hltTableView->selectionModel()->selectedRows();
  QList<const Selected*> dehlt_items;
  for (auto& sel_item : sel_indices) {
    dehlt_items << highlight_model_.getItemAt(sel_item.row());
  }
  emit clearHighlightedItems(dehlt_items);
}

void SelectHighlightWindow::zoomInHighlightedItems()
{
  auto sel_indices = ui->hltTableView->selectionModel()->selectedRows();
  QList<const Selected*> dehlt_items;
  for (auto& sel_item : sel_indices) {
    dehlt_items << highlight_model_.getItemAt(sel_item.row());
  }
  emit zoomInToItems(dehlt_items);
}

void SelectHighlightWindow::setDb(odb::dbDatabase* db)
{
  selection_model_.setDb(db);
  highlight_model_.setDb(db);
}

}  // namespace gui
<commit_msg>gui: in SelectHighlightWindow set the tab based on the current action (select/highlight)<commit_after>//////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// 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 the copyright holder 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 HOLDER 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 <QComboBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QPushButton>
#include <QSortFilterProxyModel>
#include <QString>
#include <QToolButton>
#include <QVBoxLayout>
#include <iomanip>
#include <sstream>
#include <string>

#include "gui/gui.h"
#include "highlightGroupDialog.h"
#include "selectHighlightWindow.h"

namespace gui {

static QString getBBoxString(odb::Rect& bbox, odb::dbDatabase* db)
{
  double to_microns = db->getChip()->getBlock()->getDbUnitsPerMicron();
  std::stringstream ss;
  ss << std::fixed << std::setprecision(5) << "(";
  ss << bbox.xMin() / to_microns << ",";
  ss << bbox.yMin() / to_microns << "), (";
  ss << bbox.xMax() / to_microns << ",";
  ss << bbox.yMax() / to_microns << ")";
  return QString::fromStdString(ss.str());
}

SelectionModel::SelectionModel(const SelectionSet& objs)
    : db_(nullptr), objs_(objs)
{
}

void SelectionModel::populateModel()
{
  beginResetModel();
  table_data_.clear();
  table_data_.reserve(objs_.size());
  for (auto& obj : objs_) {
    table_data_.push_back(&obj);
  }
  endResetModel();
}

int SelectionModel::rowCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return objs_.size();
}

int SelectionModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return 3;
}

QVariant SelectionModel::data(const QModelIndex& index, int role) const
{
  if (!index.isValid() || role != Qt::DisplayRole) {
    return QVariant();
  }
  unsigned int row_index = index.row();
  if (row_index > table_data_.size())
    return QVariant();
  const std::string obj_name = table_data_[row_index]->getName();
  const std::string obj_type = table_data_[row_index]->getTypeName();
  if (index.column() == 0) {
    return QString::fromStdString(obj_name);
  } else if (index.column() == 1) {
    return QString::fromStdString(obj_type);
  } else if (index.column() == 2) {
    odb::Rect bbox;
    bool valid = table_data_[row_index]->getBBox(bbox);
    return valid ? getBBoxString(bbox, db_) : "<none>";
  }
  return QVariant();
}

QVariant SelectionModel::headerData(int section,
                                    Qt::Orientation orientation,
                                    int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
    if (section == 0) {
      return QString("Object");
    } else if (section == 1) {
      return QString("Type");
    } else if (section == 2) {
      return QString("Bounds");
    }
  }
  return QVariant();
}

HighlightModel::HighlightModel(const HighlightSet& objs)
    : db_(nullptr), objs_(objs)
{
}

void HighlightModel::populateModel()
{
  beginResetModel();
  table_data_.clear();
  table_data_.reserve(objs_.size());
  int highlight_group = 0;
  for (auto& highlight_objs : objs_) {
    for (auto& obj : highlight_objs) {
      table_data_.push_back(std::make_pair(highlight_group, &obj));
    }
    ++highlight_group;
  }
  endResetModel();
}

int HighlightModel::rowCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return table_data_.size();
}

int HighlightModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return 4;
}

QVariant HighlightModel::data(const QModelIndex& index, int role) const
{
  if (!index.isValid()
      || (role != Qt::DisplayRole && role != Qt::EditRole
          && role != Qt::BackgroundRole)) {
    return QVariant();
  }
  if (role == Qt::BackgroundRole && index.column() != 3)
    return QVariant();
  else if (role == Qt::BackgroundRole && index.column() == 3) {
    auto highlight_color
        = Painter::highlightColors[table_data_[index.row()].first];
    return QColor(highlight_color.r, highlight_color.g, highlight_color.b, 100);
  }
  unsigned int row_index = index.row();
  if (row_index > table_data_.size())
    return QVariant();
  std::string obj_name = table_data_[row_index].second->getName();
  std::string obj_type("");
  if (obj_name.rfind("Net: ", 0) == 0) {
    obj_name = obj_name.substr(5);
    obj_type = "Net";
  } else if (obj_name.rfind("Inst: ", 0) == 0) {
    obj_name = obj_name.substr(6);
    obj_type = "Instance";
  }
  if (index.column() == 0) {
    return QString::fromStdString(obj_name);
  } else if (index.column() == 1) {
    return QString::fromStdString(obj_type);
  } else if (index.column() == 2) {
    odb::Rect bbox;
    bool valid = table_data_[row_index].second->getBBox(bbox);
    return valid ? getBBoxString(bbox, db_) : "<none>";
  } else if (index.column() == 3) {
    return QString("Group ")
           + QString::number(table_data_[row_index].first + 1);
  }
  return QVariant();
}

QVariant HighlightModel::headerData(int section,
                                    Qt::Orientation orientation,
                                    int role) const
{
  if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
    if (section == 0) {
      return QString("Object");
    } else if (section == 1) {
      return QString("Type");
    } else if (section == 2) {
      return QString("Bounds");
    } else if (section == 3) {
      return QString("Highlight Group");
    }
  }
  return QVariant();
}

int HighlightModel::highlightGroup(const QModelIndex& index) const
{
  int row_index = index.row();
  return table_data_[row_index].first;
}

bool HighlightModel::setData(const QModelIndex& index,
                             const QVariant& value,
                             int role)
{
  return false;
}

HighlightGroupDelegate::HighlightGroupDelegate(QObject* parent)
    : QStyledItemDelegate(parent)
{
  items_.push_back("Group 1");
  items_.push_back("Group 2");
  items_.push_back("Group 3");
  items_.push_back("Group 4");
  items_.push_back("Group 5");
  items_.push_back("Group 6");
  items_.push_back("Group 7");
  items_.push_back("Group 8");
}

QWidget* HighlightGroupDelegate::createEditor(
    QWidget* parent,
    const QStyleOptionViewItem& /* option */,
    const QModelIndex& index) const
{
  QComboBox* editor = new QComboBox(parent);
  for (unsigned int i = 0; i < items_.size(); ++i) {
    editor->addItem(items_[i].c_str());
  }
  editor->setFrame(true);
  editor->setEditable(true);
  return editor;
}

void HighlightGroupDelegate::setEditorData(QWidget* editor,
                                           const QModelIndex& index) const
{
  QString value = index.model()->data(index, Qt::EditRole).toString();
  QComboBox* combo_box = static_cast<QComboBox*>(editor);
  combo_box->setCurrentText(value);
}

void HighlightGroupDelegate::setModelData(QWidget* editor,
                                          QAbstractItemModel* model,
                                          const QModelIndex& index) const
{
  QComboBox* combo_box = static_cast<QComboBox*>(editor);
  model->setData(index, combo_box->currentIndex(), Qt::EditRole);
}

void HighlightGroupDelegate::updateEditorGeometry(
    QWidget* editor,
    const QStyleOptionViewItem& option,
    const QModelIndex& /* index */) const
{
  editor->setGeometry(option.rect);
}

void HighlightGroupDelegate::paint(QPainter* painter,
                                   const QStyleOptionViewItem& option,
                                   const QModelIndex& index) const
{
  QStyleOptionViewItem my_option = option;

  QString text = index.model()->data(index, Qt::EditRole).toString();
  my_option.text = text;
  QApplication::style()->drawControl(
      QStyle::CE_ItemViewItem, &my_option, painter);
}

SelectHighlightWindow::SelectHighlightWindow(const SelectionSet& sel_set,
                                             const HighlightSet& hlt_set,
                                             QWidget* parent)
    : QDockWidget(parent),
      ui(new Ui::SelectHighlightWidget),
      selection_model_(sel_set),
      highlight_model_(hlt_set),
      select_context_menu_(new QMenu(this)),
      highlight_context_menu_(new QMenu(this))
{
  ui->setupUi(this);

  QSortFilterProxyModel* sel_filter_proxy = new QSortFilterProxyModel(this);
  sel_filter_proxy->setSourceModel(&selection_model_);

  QSortFilterProxyModel* hlt_filter_proxy = new QSortFilterProxyModel(this);
  hlt_filter_proxy->setSourceModel(&highlight_model_);

  ui->selTableView->setModel(sel_filter_proxy);
  ui->hltTableView->setModel(hlt_filter_proxy);

  connect(ui->findEditInSel, &QLineEdit::returnPressed, this, [this]() {
    this->ui->selTableView->keyboardSearch(ui->findEditInSel->text());
  });
  connect(ui->findEditInHlt, &QLineEdit::returnPressed, this, [this]() {
    this->ui->hltTableView->keyboardSearch(ui->findEditInSel->text());
  });

  connect(ui->selTableView,
          SIGNAL(customContextMenuRequested(QPoint)),
          this,
          SLOT(showSelectCustomMenu(QPoint)));
  connect(ui->hltTableView,
          SIGNAL(customContextMenuRequested(QPoint)),
          this,
          SLOT(showHighlightCustomMenu(QPoint)));
  ui->selTableView->horizontalHeader()->setSectionResizeMode(
      QHeaderView::Stretch);
  ui->hltTableView->horizontalHeader()->setSectionResizeMode(
      QHeaderView::Stretch);

  QAction* remove_sel_item_act = select_context_menu_->addAction("De-Select");
  QAction* remove_all_sel_items = select_context_menu_->addAction("Clear All");
  QAction* highlight_sel_item_act
      = select_context_menu_->addAction("Highlight");
  select_context_menu_->addSeparator();
  QAction* show_sel_item_act
      = select_context_menu_->addAction("Zoom In Layout");

  connect(
      remove_sel_item_act, SIGNAL(triggered()), this, SLOT(deselectItems()));
  connect(remove_all_sel_items, &QAction::triggered, this, [this]() {
    emit clearAllSelections();
  });
  connect(highlight_sel_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(highlightSelectedItems()));
  connect(show_sel_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(zoomInSelectedItems()));

  QAction* remove_hlt_item_act
      = highlight_context_menu_->addAction("De-Highlight");
  QAction* remove_all_hlt_items
      = highlight_context_menu_->addAction("Clear All");
  highlight_context_menu_->addSeparator();
  QAction* show_hlt_item_act
      = highlight_context_menu_->addAction("Zoom In Layout");

  connect(
      remove_hlt_item_act, SIGNAL(triggered()), this, SLOT(dehighlightItems()));
  connect(remove_all_hlt_items, &QAction::triggered, this, [this]() {
    emit clearAllHighlights();
  });
  connect(show_hlt_item_act,
          SIGNAL(triggered()),
          this,
          SLOT(zoomInHighlightedItems()));

  ui->selTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
  ui->hltTableView->setSelectionBehavior(QAbstractItemView::SelectRows);

  ui->tabWidget->setCurrentIndex(0);
}

SelectHighlightWindow::~SelectHighlightWindow()
{
}

void SelectHighlightWindow::updateSelectionModel()
{
  selection_model_.populateModel();
  ui->tabWidget->setCurrentWidget(ui->selTab);
}

void SelectHighlightWindow::updateHighlightModel()
{
  highlight_model_.populateModel();
  ui->tabWidget->setCurrentWidget(ui->hltTab);
}

void SelectHighlightWindow::showSelectCustomMenu(QPoint pos)
{
  select_context_menu_->popup(ui->selTableView->viewport()->mapToGlobal(pos));
}

void SelectHighlightWindow::showHighlightCustomMenu(QPoint pos)
{
  highlight_context_menu_->popup(
      ui->hltTableView->viewport()->mapToGlobal(pos));
}

void SelectHighlightWindow::deselectItems()
{
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> desel_items;
  for (auto& sel_item : sel_indices) {
    desel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit clearSelectedItems(desel_items);
}
void SelectHighlightWindow::highlightSelectedItems()
{
  HighlightGroupDialog dlg;
  dlg.exec();
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> sel_items;
  for (auto& sel_item : sel_indices) {
    sel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit highlightSelectedItemsSig(sel_items, dlg.getSelectedHighlightGroup());
}

void SelectHighlightWindow::zoomInSelectedItems()
{
  auto sel_indices = ui->selTableView->selectionModel()->selectedRows();
  QList<const Selected*> desel_items;
  for (auto& sel_item : sel_indices) {
    desel_items << selection_model_.getItemAt(sel_item.row());
  }
  emit zoomInToItems(desel_items);
}

void SelectHighlightWindow::dehighlightItems()
{
  auto sel_indices = ui->hltTableView->selectionModel()->selectedRows();
  QList<const Selected*> dehlt_items;
  for (auto& sel_item : sel_indices) {
    dehlt_items << highlight_model_.getItemAt(sel_item.row());
  }
  emit clearHighlightedItems(dehlt_items);
}

void SelectHighlightWindow::zoomInHighlightedItems()
{
  auto sel_indices = ui->hltTableView->selectionModel()->selectedRows();
  QList<const Selected*> dehlt_items;
  for (auto& sel_item : sel_indices) {
    dehlt_items << highlight_model_.getItemAt(sel_item.row());
  }
  emit zoomInToItems(dehlt_items);
}

void SelectHighlightWindow::setDb(odb::dbDatabase* db)
{
  selection_model_.setDb(db);
  highlight_model_.setDb(db);
}

}  // namespace gui
<|endoftext|>


<commit_before>/*
 * tanuki.cpp
 *
 *  Created on: Oct 3, 2013
 *      Author: user
 */

/* return 0 when successed. */

#include <fstream>
#include <sstream>
#include <algorithm>

#include "HttpSocket.hpp"
#include "AnimeDbFinder.hpp"
#include "ArgumentsParser.hpp"
#include "common.hpp"
#include "SearchParser.hpp"

#include "AnimeArtFinder.hpp"
#include "DanbooruArtFinder.hpp"
#include "OnAnimeFinder.hpp"

#include "Debug.hpp"

static const char* dbFile = "/tmp/anidb_list.data";
static const char* searchFileRes = "/tmp/anidb_search.";

static const char * dbFileUrl = "http://anidb.net/api/anime-titles.dat.gz";
static const char * requestQuery = "http://api.anidb.net:9001/httpapi?request=anime&client=xtreamerscraper&clientver=1&protover=1&aid=";

bool download_dbFile() {

	std::ofstream outFile;
	outFile.open(dbFile, std::ios::out | std::ios::binary);

	if (!outFile.good()) {

		outFile.close();
		return false;
	}

	HttpGetter getter;
	std::string query(dbFileUrl);
	getter.readContent(query, 80, outFile);
	outFile.close();
	TRACE("download db file")
	return true;
}

bool download_searchFile(const std::string& searchId, std::stringbuf& infoSearchResult) {

	std::ostream outFile(&infoSearchResult);
	HttpGetter getter;
	std::string query(requestQuery);
	query.append(searchId);
	getter.readContent(query, 9001, outFile);
	return true;
}

bool parser_search_api_file(std::stringbuf& infoSearchResult, const std::string& outputFile) {

	std::istream in(&infoSearchResult);
	InfoResult result = { };
	SearchParser parser;

	if (!parser.parse(in, result)) {

		return false;
	}

	in.seekg(0, std::ios::beg);
	std::vector<std::string> titles;
	parser.parseTitles(in, titles);

	if(!titles.empty())
	{
		ART_FINDER_3(AnimeArtFinder, DanbooruArtFinder, OnAnimeFinder) finder(titles);
		//ART_FINDER_1(AnimePicFinder) finder(titles);
		finder.getAnimeArts(result.fanart);
	}

	std::ofstream outFile;
	outFile.open(outputFile.c_str(), std::ios::out | std::ios::binary);
	bool infoResultGenerated = false;

	if ((infoResultGenerated = outFile.good())) {

		GenInfoResult(result, outFile);
	}

	outFile.close();
	return infoResultGenerated;
}

bool get_Elements_from_db(const std::string& keyword, std::vector<Element>& elementsInDb)
{
	std::ifstream inFile;
	inFile.open(dbFile, std::ios::in | std::ios::binary);

	if(!inFile.good())
	{
		inFile.close();
		return false;
	}

	AnimeDbFinder finder;
//	Element element = {};
//	finder.findInDb(inFile, keyword,element);
//	elementsInDb.push_back(element);
	finder.findAllInDb(inFile, keyword, elementsInDb);
	inFile.close();

	std::sort(elementsInDb.begin(), elementsInDb.end());
	elementsInDb.erase(std::unique( elementsInDb.begin(), elementsInDb.end(), unique_Element), elementsInDb.end());
	std::sort(elementsInDb.begin(), elementsInDb.end(), sort_Element_by_power);
	return true;
}

bool generate_search_result(const char* fileName, const std::vector<Element>& elementsInDb)
{
	std::ofstream outFile;
	TRACE(fileName);
	outFile.open(fileName, std::ios::out | std::ios::binary);

	if (!outFile.good()) {

		outFile.close();
		return false;
	}

	GenSearchResult(elementsInDb, outFile);
	outFile.close();
	return true;
}

bool mainApp(int argc, char ** argv) {

	Arguments arguments(argc, argv);

	TRACE("output: " << arguments.getOutput() << ", isSearchOpt: " << arguments.isSearchOpt() << ", keyword: " << arguments.getKeyword())

	if (arguments.getOutput().empty() || arguments.getKeyword().empty()) {
		return false;
	}

	if (arguments.isSearchOpt()) {

		// check for already download db file and download if not exists
		if (!file_exists(dbFile) && !download_dbFile()) {

			return false;
		}

		std::vector<Element> list;

		if (!get_Elements_from_db(arguments.getKeyword(), list)) {

			return false;
		}

		TRACE(list)

		if(!generate_search_result(arguments.getOutput().c_str(), list))
		{
			return false;
		}

	} else {

		std::string tmpFile(searchFileRes);
		tmpFile.append(arguments.getKeyword());

		// search for processed keyword and copy if exists
		const bool fileExists = file_exists(tmpFile);

		if ((fileExists && !copy_file(tmpFile, arguments.getOutput())) || !fileExists) {

			std::stringbuf buff;
			// download new search result and parse to output xml
			if (!download_searchFile(arguments.getKeyword(), buff) || !parser_search_api_file(buff, arguments.getOutput())) {
				return false;
			}
			// backup processed file for reuse
			copy_file(arguments.getOutput(), tmpFile);
		}
	}

	TRACE("end animedb!!")
	return true;
}
<commit_msg>fix spelling<commit_after>/*
 * tanuki.cpp
 *
 *  Created on: Oct 3, 2013
 *      Author: user
 */

/* return 0 when successed. */

#include <fstream>
#include <sstream>
#include <algorithm>

#include "HttpSocket.hpp"
#include "AnimeDbFinder.hpp"
#include "ArgumentsParser.hpp"
#include "common.hpp"
#include "SearchParser.hpp"

#include "AnimeArtFinder.hpp"
#include "DanbooruArtFinder.hpp"
#include "OnAnimeFinder.hpp"

#include "Debug.hpp"

static const char* dbFile = "/tmp/anidb_list.data";
static const char* searchFileRes = "/tmp/anidb_search.";

static const char * dbFileUrl = "http://anidb.net/api/anime-titles.dat.gz";
static const char * requestQuery = "http://api.anidb.net:9001/httpapi?request=anime&client=xtreamerscraper&clientver=1&protover=1&aid=";

bool download_dbFile() {

	std::ofstream outFile;
	outFile.open(dbFile, std::ios::out | std::ios::binary);

	if (!outFile.good()) {

		outFile.close();
		return false;
	}

	HttpGetter getter;
	std::string query(dbFileUrl);
	getter.readContent(query, 80, outFile);
	outFile.close();
	TRACE("download db file")
	return true;
}

bool download_searchFile(const std::string& searchId, std::stringbuf& infoSearchResult) {

	std::ostream outFile(&infoSearchResult);
	HttpGetter getter;
	std::string query(requestQuery);
	query.append(searchId);
	getter.readContent(query, 9001, outFile);
	return true;
}

bool parser_search_api_file(std::stringbuf& infoSearchResult, const std::string& outputFile) {

	std::istream in(&infoSearchResult);
	InfoResult result = { };
	SearchParser parser;

	if (!parser.parse(in, result)) {

		return false;
	}

	in.seekg(0, std::ios::beg);
	std::vector<std::string> titles;
	parser.parseTitles(in, titles);

	if(!titles.empty())
	{
		ART_FINDER_3(AnimePicFinder, DanbooruArtFinder, OnAnimeFinder) finder(titles);
		//ART_FINDER_1(AnimePicFinder) finder(titles);
		finder.getAnimeArts(result.fanart);
	}

	std::ofstream outFile;
	outFile.open(outputFile.c_str(), std::ios::out | std::ios::binary);
	bool infoResultGenerated = false;

	if ((infoResultGenerated = outFile.good())) {

		GenInfoResult(result, outFile);
	}

	outFile.close();
	return infoResultGenerated;
}

bool get_Elements_from_db(const std::string& keyword, std::vector<Element>& elementsInDb)
{
	std::ifstream inFile;
	inFile.open(dbFile, std::ios::in | std::ios::binary);

	if(!inFile.good())
	{
		inFile.close();
		return false;
	}

	AnimeDbFinder finder;
//	Element element = {};
//	finder.findInDb(inFile, keyword,element);
//	elementsInDb.push_back(element);
	finder.findAllInDb(inFile, keyword, elementsInDb);
	inFile.close();

	std::sort(elementsInDb.begin(), elementsInDb.end());
	elementsInDb.erase(std::unique( elementsInDb.begin(), elementsInDb.end(), unique_Element), elementsInDb.end());
	std::sort(elementsInDb.begin(), elementsInDb.end(), sort_Element_by_power);
	return true;
}

bool generate_search_result(const char* fileName, const std::vector<Element>& elementsInDb)
{
	std::ofstream outFile;
	TRACE(fileName);
	outFile.open(fileName, std::ios::out | std::ios::binary);

	if (!outFile.good()) {

		outFile.close();
		return false;
	}

	GenSearchResult(elementsInDb, outFile);
	outFile.close();
	return true;
}

bool mainApp(int argc, char ** argv) {

	Arguments arguments(argc, argv);

	TRACE("output: " << arguments.getOutput() << ", isSearchOpt: " << arguments.isSearchOpt() << ", keyword: " << arguments.getKeyword())

	if (arguments.getOutput().empty() || arguments.getKeyword().empty()) {
		return false;
	}

	if (arguments.isSearchOpt()) {

		// check for already download db file and download if not exists
		if (!file_exists(dbFile) && !download_dbFile()) {

			return false;
		}

		std::vector<Element> list;

		if (!get_Elements_from_db(arguments.getKeyword(), list)) {

			return false;
		}

		TRACE(list)

		if(!generate_search_result(arguments.getOutput().c_str(), list))
		{
			return false;
		}

	} else {

		std::string tmpFile(searchFileRes);
		tmpFile.append(arguments.getKeyword());

		// search for processed keyword and copy if exists
		const bool fileExists = file_exists(tmpFile);

		if ((fileExists && !copy_file(tmpFile, arguments.getOutput())) || !fileExists) {

			std::stringbuf buff;
			// download new search result and parse to output xml
			if (!download_searchFile(arguments.getKeyword(), buff) || !parser_search_api_file(buff, arguments.getOutput())) {
				return false;
			}
			// backup processed file for reuse
			copy_file(arguments.getOutput(), tmpFile);
		}
	}

	TRACE("end animedb!!")
	return true;
}
<|endoftext|>


<commit_before>/* libs/graphics/effects/SkCullPoints.cpp
**
** Copyright 2006, Google Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** 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.
*/

#include "SkCullPoints.h"
#include "Sk64.h"

static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy)
{
#if 0
    return v.fX * dy - v.fY * dx < 0;
#else
    Sk64   tmp0, tmp1;

    tmp0.setMul(v.fX, dy);
    tmp1.setMul(dx, v.fY);
    tmp0.sub(tmp1);
    return tmp0.isNeg();
#endif
}

bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const
{
    const SkIRect& r = fR;

    if (x0 < r.fLeft    && x1 < r.fLeft ||
        x0 > r.fRight   && x1 > r.fRight ||
        y0 < r.fTop     && y1 < r.fTop ||
        y0 > r.fBottom  && y1 > r.fBottom)
        return false;

    // since the crossprod test is a little expensive, check for easy-in cases first
    if (r.contains(x0, y0) || r.contains(x1, y1))
        return true;

    // At this point we're not sure, so we do a crossprod test
    SkIPoint           vec;
    const SkIPoint*    rAsQuad = fAsQuad;

    vec.set(x1 - x0, y1 - y0);
    bool isNeg = cross_product_is_neg(vec, x0 - rAsQuad[0].fX, y0 - rAsQuad[0].fY);
    for (int i = 1; i < 4; i++) {
        if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg)
        {
            return true;
        }
    }
    return false;   // we didn't intersect
}

static void toQuad(const SkIRect& r, SkIPoint quad[4])
{
    SkASSERT(quad);

    quad[0].set(r.fLeft, r.fTop);
    quad[1].set(r.fRight, r.fTop);
    quad[2].set(r.fRight, r.fBottom);
    quad[3].set(r.fLeft, r.fBottom);
}

SkCullPoints::SkCullPoints()
{
    SkIRect    r;
    r.setEmpty();
    this->reset(r);
}

SkCullPoints::SkCullPoints(const SkIRect& r)
{
    this->reset(r);
}

void SkCullPoints::reset(const SkIRect& r)
{
    fR = r;
    toQuad(fR, fAsQuad);
    fPrevPt.set(0, 0);
    fPrevResult = kNo_Result;
}

void SkCullPoints::moveTo(int x, int y)
{
    fPrevPt.set(x, y);
    fPrevResult = kNo_Result;   // so we trigger a movetolineto later
}

SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
{
    SkASSERT(line != NULL);

    LineToResult result = kNo_Result;
    int x0 = fPrevPt.fX;
    int y0 = fPrevPt.fY;

    // need to upgrade sect_test to chop the result
    // and to correctly return kLineTo_Result when the result is connected
    // to the previous call-out
    if (this->sect_test(x0, y0, x, y))
    {
        line[0].set(x0, y0);
        line[1].set(x, y);

        if (fPrevResult != kNo_Result && fPrevPt.equals(x0, y0))
            result = kLineTo_Result;
        else
            result = kMoveToLineTo_Result;
    }

    fPrevPt.set(x, y);
    fPrevResult = result;

    return result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////

#include "SkPath.h"

SkCullPointsPath::SkCullPointsPath()
    : fCP(), fPath(NULL)
{
}

SkCullPointsPath::SkCullPointsPath(const SkIRect& r, SkPath* dst)
    : fCP(r), fPath(dst)
{
}

void SkCullPointsPath::reset(const SkIRect& r, SkPath* dst)
{
    fCP.reset(r);
    fPath = dst;
}

void SkCullPointsPath::moveTo(int x, int y)
{
    fCP.moveTo(x, y);
}

void SkCullPointsPath::lineTo(int x, int y)
{
    SkIPoint   pts[2];

    switch (fCP.lineTo(x, y, pts)) {
    case SkCullPoints::kMoveToLineTo_Result:
        fPath->moveTo(SkIntToScalar(pts[0].fX), SkIntToScalar(pts[0].fY));
        // fall through to the lineto case
    case SkCullPoints::kLineTo_Result:
        fPath->lineTo(SkIntToScalar(pts[1].fX), SkIntToScalar(pts[1].fY));
        break;
    default:
        break;
    }
}

<commit_msg>Add suggested parentheses to fix build with GCC 4.3<commit_after>/* libs/graphics/effects/SkCullPoints.cpp
**
** Copyright 2006, Google Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** 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.
*/

#include "SkCullPoints.h"
#include "Sk64.h"

static bool cross_product_is_neg(const SkIPoint& v, int dx, int dy)
{
#if 0
    return v.fX * dy - v.fY * dx < 0;
#else
    Sk64   tmp0, tmp1;

    tmp0.setMul(v.fX, dy);
    tmp1.setMul(dx, v.fY);
    tmp0.sub(tmp1);
    return tmp0.isNeg();
#endif
}

bool SkCullPoints::sect_test(int x0, int y0, int x1, int y1) const
{
    const SkIRect& r = fR;

    if ((x0 < r.fLeft    && x1 < r.fLeft) ||
        (x0 > r.fRight   && x1 > r.fRight) ||
        (y0 < r.fTop     && y1 < r.fTop) ||
        (y0 > r.fBottom  && y1 > r.fBottom))
        return false;

    // since the crossprod test is a little expensive, check for easy-in cases first
    if (r.contains(x0, y0) || r.contains(x1, y1))
        return true;

    // At this point we're not sure, so we do a crossprod test
    SkIPoint           vec;
    const SkIPoint*    rAsQuad = fAsQuad;

    vec.set(x1 - x0, y1 - y0);
    bool isNeg = cross_product_is_neg(vec, x0 - rAsQuad[0].fX, y0 - rAsQuad[0].fY);
    for (int i = 1; i < 4; i++) {
        if (cross_product_is_neg(vec, x0 - rAsQuad[i].fX, y0 - rAsQuad[i].fY) != isNeg)
        {
            return true;
        }
    }
    return false;   // we didn't intersect
}

static void toQuad(const SkIRect& r, SkIPoint quad[4])
{
    SkASSERT(quad);

    quad[0].set(r.fLeft, r.fTop);
    quad[1].set(r.fRight, r.fTop);
    quad[2].set(r.fRight, r.fBottom);
    quad[3].set(r.fLeft, r.fBottom);
}

SkCullPoints::SkCullPoints()
{
    SkIRect    r;
    r.setEmpty();
    this->reset(r);
}

SkCullPoints::SkCullPoints(const SkIRect& r)
{
    this->reset(r);
}

void SkCullPoints::reset(const SkIRect& r)
{
    fR = r;
    toQuad(fR, fAsQuad);
    fPrevPt.set(0, 0);
    fPrevResult = kNo_Result;
}

void SkCullPoints::moveTo(int x, int y)
{
    fPrevPt.set(x, y);
    fPrevResult = kNo_Result;   // so we trigger a movetolineto later
}

SkCullPoints::LineToResult SkCullPoints::lineTo(int x, int y, SkIPoint line[])
{
    SkASSERT(line != NULL);

    LineToResult result = kNo_Result;
    int x0 = fPrevPt.fX;
    int y0 = fPrevPt.fY;

    // need to upgrade sect_test to chop the result
    // and to correctly return kLineTo_Result when the result is connected
    // to the previous call-out
    if (this->sect_test(x0, y0, x, y))
    {
        line[0].set(x0, y0);
        line[1].set(x, y);

        if (fPrevResult != kNo_Result && fPrevPt.equals(x0, y0))
            result = kLineTo_Result;
        else
            result = kMoveToLineTo_Result;
    }

    fPrevPt.set(x, y);
    fPrevResult = result;

    return result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////

#include "SkPath.h"

SkCullPointsPath::SkCullPointsPath()
    : fCP(), fPath(NULL)
{
}

SkCullPointsPath::SkCullPointsPath(const SkIRect& r, SkPath* dst)
    : fCP(r), fPath(dst)
{
}

void SkCullPointsPath::reset(const SkIRect& r, SkPath* dst)
{
    fCP.reset(r);
    fPath = dst;
}

void SkCullPointsPath::moveTo(int x, int y)
{
    fCP.moveTo(x, y);
}

void SkCullPointsPath::lineTo(int x, int y)
{
    SkIPoint   pts[2];

    switch (fCP.lineTo(x, y, pts)) {
    case SkCullPoints::kMoveToLineTo_Result:
        fPath->moveTo(SkIntToScalar(pts[0].fX), SkIntToScalar(pts[0].fY));
        // fall through to the lineto case
    case SkCullPoints::kLineTo_Result:
        fPath->lineTo(SkIntToScalar(pts[1].fX), SkIntToScalar(pts[1].fY));
        break;
    default:
        break;
    }
}

<|endoftext|>


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

#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;

class KeybindingApiTest : public ExtensionApiTest {
 public:
  KeybindingApiTest() {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalExtensionApis);
  }
  virtual ~KeybindingApiTest() {}

 protected:
  BrowserActionTestUtil GetBrowserActionsBar() {
    return BrowserActionTestUtil(browser());
  }

  bool OpenPopup(int index) {
    ResultCatcher catcher;
    ui_test_utils::WindowedNotificationObserver popup_observer(
        content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
        content::NotificationService::AllSources());
    GetBrowserActionsBar().Press(index);
    popup_observer.Wait();
    EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    return GetBrowserActionsBar().HasPopup();
  }
};

#if defined(OS_WIN)  // Not implemented on other platforms yet.
IN_PROC_BROWSER_TEST_F(KeybindingApiTest, Basic) {
  ASSERT_TRUE(test_server()->Start());
  ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_;
  const Extension* extension = GetSingleLoadedExtension();
  ASSERT_TRUE(extension) << message_;

  // Test that there is a browser action in the toolbar.
  ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());

  ui_test_utils::NavigateToURL(browser(),
      test_server()->GetURL("files/extensions/test_file.txt"));

  // Simulate the browser action being clicked (Ctrl+Shift+F).
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
      browser(), ui::VKEY_F, true, true, false, false));

  // Verify the command worked.
  WebContents* tab = browser()->GetSelectedWebContents();
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->GetRenderViewHost(), L"",
      L"setInterval(function(){"
      L"  if(document.body.bgColor == 'red'){"
      L"    window.domAutomationController.send(true)}}, 100)",
      &result));
  ASSERT_TRUE(result);

  // Simulate the event being sent (Ctrl+Shift+Y).
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
      browser(), ui::VKEY_Y, true, true, false, false));

  result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->GetRenderViewHost(), L"",
      L"setInterval(function(){"
      L"  if(document.body.bgColor == 'blue'){"
      L"    window.domAutomationController.send(true)}}, 100)",
      &result));
  ASSERT_TRUE(result);
}
#endif  // OS_WIN
<commit_msg>Enable the keybinding test for TOOLKIT_VIEWS.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/browser_action_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"

using content::WebContents;

class KeybindingApiTest : public ExtensionApiTest {
 public:
  KeybindingApiTest() {
    CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalExtensionApis);
  }
  virtual ~KeybindingApiTest() {}

 protected:
  BrowserActionTestUtil GetBrowserActionsBar() {
    return BrowserActionTestUtil(browser());
  }

  bool OpenPopup(int index) {
    ResultCatcher catcher;
    ui_test_utils::WindowedNotificationObserver popup_observer(
        content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
        content::NotificationService::AllSources());
    GetBrowserActionsBar().Press(index);
    popup_observer.Wait();
    EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    return GetBrowserActionsBar().HasPopup();
  }
};

#if defined(TOOLKIT_VIEWS)  // Not implemented on other platforms yet.
IN_PROC_BROWSER_TEST_F(KeybindingApiTest, Basic) {
  ASSERT_TRUE(test_server()->Start());
  ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_;
  const Extension* extension = GetSingleLoadedExtension();
  ASSERT_TRUE(extension) << message_;

  // Test that there is a browser action in the toolbar.
  ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());

  ui_test_utils::NavigateToURL(browser(),
      test_server()->GetURL("files/extensions/test_file.txt"));

  // Simulate the browser action being clicked (Ctrl+Shift+F).
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
      browser(), ui::VKEY_F, true, true, false, false));

  // Verify the command worked.
  WebContents* tab = browser()->GetSelectedWebContents();
  bool result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->GetRenderViewHost(), L"",
      L"setInterval(function(){"
      L"  if(document.body.bgColor == 'red'){"
      L"    window.domAutomationController.send(true)}}, 100)",
      &result));
  ASSERT_TRUE(result);

  // Simulate the event being sent (Ctrl+Shift+Y).
  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
      browser(), ui::VKEY_Y, true, true, false, false));

  result = false;
  ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool(
      tab->GetRenderViewHost(), L"",
      L"setInterval(function(){"
      L"  if(document.body.bgColor == 'blue'){"
      L"    window.domAutomationController.send(true)}}, 100)",
      &result));
  ASSERT_TRUE(result);
}
#endif  // TOOLKIT_VIEWS
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "common/RhoPort.h"
#include "common/StringConverter.h"
#include "ruby/ext/rho/rhoruby.h"
#include "MainWindow.h"

#ifdef OS_WINCE__
#include <tapi.h>
#include <tsp.h>
//#include <sms.h>
#endif

using namespace rho;
using namespace rho::common;
extern "C" HWND getMainWnd();

extern "C"
{
#ifdef OS_WINCE__

static const int PHONE_NUMBER_BUFFER_SIZE = 512;

bool getPhoneNumFromSIMCard (String &number)
{

#define EXIT_ON_NULL(_p) if (_p == NULL){ hr = E_OUTOFMEMORY; goto FuncExit; }
#define EXIT_ON_FALSE(_f) if (!(_f)) { hr = E_FAIL; goto FuncExit; }
#define MAX(i, j)   ((i) > (j) ? (i) : (j))

	const int TAPI_API_LOW_VERSION  = 0x00020000;
	const int TAPI_API_HIGH_VERSION = 0x00020000;
	const int LINE_NUMBER = 1;

    HRESULT  hr = E_FAIL;
    LRESULT  lResult = 0;
    HLINEAPP hLineApp;
    DWORD    dwNumDevs;
    DWORD    dwAPIVersion = TAPI_API_HIGH_VERSION;
    LINEINITIALIZEEXPARAMS liep;

    DWORD dwTAPILineDeviceID;
    const DWORD dwAddressID = LINE_NUMBER - 1;

    liep.dwTotalSize = sizeof(liep);
    liep.dwOptions   = LINEINITIALIZEEXOPTION_USEEVENT;

    if (SUCCEEDED(lineInitializeEx(&hLineApp, 0, 0, TEXT("ExTapi_Lib"), &dwNumDevs, &dwAPIVersion, &liep))) {
        BYTE* pCapBuf = NULL;
        DWORD dwCapBufSize = PHONE_NUMBER_BUFFER_SIZE;
        LINEEXTENSIONID  LineExtensionID;
        LINEDEVCAPS*     pLineDevCaps = NULL;
        LINEADDRESSCAPS* placAddressCaps = NULL;

        pCapBuf = new BYTE[dwCapBufSize];
        EXIT_ON_NULL(pCapBuf);

        pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
        pLineDevCaps->dwTotalSize = dwCapBufSize;

        // Get TSP Line Device ID
        dwTAPILineDeviceID = 0xffffffff;
        for (DWORD dwCurrentDevID = 0 ; dwCurrentDevID < dwNumDevs ; dwCurrentDevID++) {
            if (0 == lineNegotiateAPIVersion(hLineApp, dwCurrentDevID, TAPI_API_LOW_VERSION, TAPI_API_HIGH_VERSION,
                &dwAPIVersion, &LineExtensionID)) {
                lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);

                if (dwCapBufSize < pLineDevCaps->dwNeededSize) {
                    delete[] pCapBuf;
                    dwCapBufSize = pLineDevCaps->dwNeededSize;
                    pCapBuf = new BYTE[dwCapBufSize];
                    EXIT_ON_NULL(pCapBuf);

                    pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
                    pLineDevCaps->dwTotalSize = dwCapBufSize;

                    lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);
                }

                if ((0 == lResult) &&
                    (0 == _tcscmp((TCHAR*)((BYTE*)pLineDevCaps+pLineDevCaps->dwLineNameOffset), CELLTSP_LINENAME_STRING))) {
                    dwTAPILineDeviceID = dwCurrentDevID;
                    break;
                }
            }
        }

        placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
        placAddressCaps->dwTotalSize = dwCapBufSize;

        lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);

        if (dwCapBufSize < placAddressCaps->dwNeededSize) {
            delete[] pCapBuf;
            dwCapBufSize = placAddressCaps->dwNeededSize;
            pCapBuf = new BYTE[dwCapBufSize];
            EXIT_ON_NULL(pCapBuf);

            placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
            placAddressCaps->dwTotalSize = dwCapBufSize;

            lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);
        }

        if (0 == lResult) {
			EXIT_ON_FALSE(0 != placAddressCaps->dwAddressSize);

			// A non-zero dwAddressSize means a phone number was found
			ASSERT(0 != placAddressCaps->dwAddressOffset);
			PWCHAR tsAddress = (WCHAR*)(((BYTE*)placAddressCaps)+placAddressCaps->dwAddressOffset);
			number = convertToStringA (tsAddress);

            hr = S_OK;
        }

        delete[] pCapBuf;
    } // End if ()

FuncExit:
    lineShutdown(hLineApp);

	if (hr != S_OK) {
		LOG(ERROR) + "failed to get phone number from SIM";
		return false;
	}

    return true;

#undef EXIT_ON_NULL
#undef EXIT_ON_FALSE
#undef MAX

}
/*
bool getPhoneNumFromSMSBearer (String &number)
{
	SMS_ADDRESS psmsaAddress;

	if (SmsGetPhoneNumber (&psmsaAddress) != S_OK) {
		LOG(ERROR) + "failed to get phone number using SMS bearer";
		return false;
	}

	number = convertToStringA(psmsaAddress.ptsAddress);
	return true;
} */

bool getPhoneNumFromOwnerInfo (String &number)
{
	HKEY	hKey;
	DWORD	dwType, dwCount = PHONE_NUMBER_BUFFER_SIZE;
	TCHAR   strValue [PHONE_NUMBER_BUFFER_SIZE];
	LONG    res;
	TCHAR   errMsg[1024];

	if ((res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Owner"),  NULL, KEY_EXECUTE , &hKey)) == 0)
	{
		if ((res = RegQueryValueEx (hKey, TEXT("Telephone"), NULL,  &dwType, (LPBYTE )strValue, &dwCount)) == 0)
		{
			if (dwType != REG_SZ)
			{
				LOG(ERROR) + "Settings/Owner Information/Telephone has invalid type";
				RegCloseKey(hKey);
				return false;
			}

			if (dwCount > 0)
			{
				strValue[dwCount + 1] = '\0';

				if (_tcslen((strValue))  == 0)
				{
					LOG(INFO) + "Settings/Owner Information/Telephone is empty";

					RegCloseKey(hKey);
					return false;
				}

				number = convertToStringA(strValue);

				RegCloseKey(hKey);
				return true;
			}
		}
	}

	RegCloseKey(hKey);
	FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, errMsg, sizeof(errMsg), NULL);
	LOG(ERROR) + errMsg;

	return false;
}

VALUE phone_number()
{
	String number;

	if (getPhoneNumFromSIMCard(number))
		return rho_ruby_create_string(number.c_str());

//	if (getPhoneNumFromSMSBearer(number))
//		return rho_ruby_create_string(number.c_str());

	if (getPhoneNumFromOwnerInfo(number))
		return rho_ruby_create_string(number.c_str());

	return rho_ruby_get_NIL();
}
#else
VALUE phone_number()
{
	return rho_ruby_get_NIL();
}
#endif

static int has_camera()
{
#ifdef OS_WINCE
/*    DEVMGR_DEVICE_INFORMATION devInfo = {0};
    GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93,
                        0x3E, 0x4D, 0x7E, 0x3C, 0x86 };
    devInfo.dwSize = sizeof(devInfo);

    HANDLE hDevice = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &devInfo);
    if ( hDevice != INVALID_HANDLE_VALUE )
    {
        FindClose(hDevice);
        return 1;
    }

    return 0;*/

    return 1;
#else
    return 0;
#endif
}

static double get_screen_ppi_x()
{
	HWND hWndDesktop = GetDesktopWindow();
	HDC hdcDesktop = GetDC(hWndDesktop);
	int mms = GetDeviceCaps(hdcDesktop, HORZSIZE);
	int pixels = GetDeviceCaps(hdcDesktop, HORZRES);
	double ret = (pixels*25.4)/mms;
	return ret;
}

static double get_screen_ppi_y()
{
	HWND hWndDesktop = GetDesktopWindow();
	HDC hdcDesktop = GetDC(hWndDesktop);
	int mms = GetDeviceCaps(hdcDesktop, VERTSIZE);
	int pixels = GetDeviceCaps(hdcDesktop, VERTRES);
	double ret = (pixels*25.4)/mms;
	return ret;
}

int rho_sysimpl_get_property(char* szPropName, VALUE* resValue)
{
	if (strcasecmp("has_camera",szPropName) == 0)
        {*resValue = rho_ruby_create_boolean(has_camera()); return 1;}

	if (strcasecmp("phone_number",szPropName) == 0)
        {*resValue = phone_number();return 1;}

	if (strcasecmp("ppi_x",szPropName) == 0)
        {*resValue = rho_ruby_create_double(get_screen_ppi_x()); return 1;}

	if (strcasecmp("ppi_y",szPropName) == 0)
        {*resValue = rho_ruby_create_double(get_screen_ppi_y()); return 1; }

    return 0;
}

VALUE rho_sys_get_locale()
{
    wchar_t szLang[20];
    int nRes = GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SABBREVLANGNAME , szLang, 20);
    szLang[2] = 0;
    wcslwr(szLang);

    return rho_ruby_create_string(convertToStringA(szLang).c_str());
}

int rho_sys_get_screen_width()
{
#ifdef OS_WINCE
	return GetSystemMetrics(SM_CXSCREEN);
#else
	return CMainWindow::getScreenWidth();
#endif
}

int rho_sys_get_screen_height()
{
#ifdef OS_WINCE
	return GetSystemMetrics(SM_CYSCREEN);
#else
	return CMainWindow::getScreenHeight();
#endif
}

VALUE rho_sys_makephonecall(const char* callname, int nparams, char** param_names, char** param_values)
{
	return rho_ruby_get_NIL();
}

static int g_rho_has_network = 1;

void rho_sysimpl_sethas_network(int nValue)
{
    g_rho_has_network = nValue;
}

VALUE rho_sys_has_network()
{
	return rho_ruby_create_boolean(g_rho_has_network!=0);
}

void rho_sys_app_exit()
{
	::PostMessage(getMainWnd(), WM_COMMAND, MAKEWPARAM(IDM_EXIT,0), (LPARAM )0);
}

} //extern "C"
<commit_msg>Implemented task #2948192 - system property to check for version (WM)<commit_after>#include "stdafx.h"

#include "common/RhoPort.h"
#include "common/StringConverter.h"
#include "ruby/ext/rho/rhoruby.h"
#include "MainWindow.h"

#ifdef OS_WINCE__
#include <tapi.h>
#include <tsp.h>
//#include <sms.h>
#endif

using namespace rho;
using namespace rho::common;
extern "C" HWND getMainWnd();
extern "C" char* wce_wctomb(const wchar_t* w);

extern "C"
{
#ifdef OS_WINCE__

static const int PHONE_NUMBER_BUFFER_SIZE = 512;

bool getPhoneNumFromSIMCard (String &number)
{

#define EXIT_ON_NULL(_p) if (_p == NULL){ hr = E_OUTOFMEMORY; goto FuncExit; }
#define EXIT_ON_FALSE(_f) if (!(_f)) { hr = E_FAIL; goto FuncExit; }
#define MAX(i, j)   ((i) > (j) ? (i) : (j))

	const int TAPI_API_LOW_VERSION  = 0x00020000;
	const int TAPI_API_HIGH_VERSION = 0x00020000;
	const int LINE_NUMBER = 1;

    HRESULT  hr = E_FAIL;
    LRESULT  lResult = 0;
    HLINEAPP hLineApp;
    DWORD    dwNumDevs;
    DWORD    dwAPIVersion = TAPI_API_HIGH_VERSION;
    LINEINITIALIZEEXPARAMS liep;

    DWORD dwTAPILineDeviceID;
    const DWORD dwAddressID = LINE_NUMBER - 1;

    liep.dwTotalSize = sizeof(liep);
    liep.dwOptions   = LINEINITIALIZEEXOPTION_USEEVENT;

    if (SUCCEEDED(lineInitializeEx(&hLineApp, 0, 0, TEXT("ExTapi_Lib"), &dwNumDevs, &dwAPIVersion, &liep))) {
        BYTE* pCapBuf = NULL;
        DWORD dwCapBufSize = PHONE_NUMBER_BUFFER_SIZE;
        LINEEXTENSIONID  LineExtensionID;
        LINEDEVCAPS*     pLineDevCaps = NULL;
        LINEADDRESSCAPS* placAddressCaps = NULL;

        pCapBuf = new BYTE[dwCapBufSize];
        EXIT_ON_NULL(pCapBuf);

        pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
        pLineDevCaps->dwTotalSize = dwCapBufSize;

        // Get TSP Line Device ID
        dwTAPILineDeviceID = 0xffffffff;
        for (DWORD dwCurrentDevID = 0 ; dwCurrentDevID < dwNumDevs ; dwCurrentDevID++) {
            if (0 == lineNegotiateAPIVersion(hLineApp, dwCurrentDevID, TAPI_API_LOW_VERSION, TAPI_API_HIGH_VERSION,
                &dwAPIVersion, &LineExtensionID)) {
                lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);

                if (dwCapBufSize < pLineDevCaps->dwNeededSize) {
                    delete[] pCapBuf;
                    dwCapBufSize = pLineDevCaps->dwNeededSize;
                    pCapBuf = new BYTE[dwCapBufSize];
                    EXIT_ON_NULL(pCapBuf);

                    pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
                    pLineDevCaps->dwTotalSize = dwCapBufSize;

                    lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);
                }

                if ((0 == lResult) &&
                    (0 == _tcscmp((TCHAR*)((BYTE*)pLineDevCaps+pLineDevCaps->dwLineNameOffset), CELLTSP_LINENAME_STRING))) {
                    dwTAPILineDeviceID = dwCurrentDevID;
                    break;
                }
            }
        }

        placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
        placAddressCaps->dwTotalSize = dwCapBufSize;

        lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);

        if (dwCapBufSize < placAddressCaps->dwNeededSize) {
            delete[] pCapBuf;
            dwCapBufSize = placAddressCaps->dwNeededSize;
            pCapBuf = new BYTE[dwCapBufSize];
            EXIT_ON_NULL(pCapBuf);

            placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
            placAddressCaps->dwTotalSize = dwCapBufSize;

            lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);
        }

        if (0 == lResult) {
			EXIT_ON_FALSE(0 != placAddressCaps->dwAddressSize);

			// A non-zero dwAddressSize means a phone number was found
			ASSERT(0 != placAddressCaps->dwAddressOffset);
			PWCHAR tsAddress = (WCHAR*)(((BYTE*)placAddressCaps)+placAddressCaps->dwAddressOffset);
			number = convertToStringA (tsAddress);

            hr = S_OK;
        }

        delete[] pCapBuf;
    } // End if ()

FuncExit:
    lineShutdown(hLineApp);

	if (hr != S_OK) {
		LOG(ERROR) + "failed to get phone number from SIM";
		return false;
	}

    return true;

#undef EXIT_ON_NULL
#undef EXIT_ON_FALSE
#undef MAX

}
/*
bool getPhoneNumFromSMSBearer (String &number)
{
	SMS_ADDRESS psmsaAddress;

	if (SmsGetPhoneNumber (&psmsaAddress) != S_OK) {
		LOG(ERROR) + "failed to get phone number using SMS bearer";
		return false;
	}

	number = convertToStringA(psmsaAddress.ptsAddress);
	return true;
} */

bool getPhoneNumFromOwnerInfo (String &number)
{
	HKEY	hKey;
	DWORD	dwType, dwCount = PHONE_NUMBER_BUFFER_SIZE;
	TCHAR   strValue [PHONE_NUMBER_BUFFER_SIZE];
	LONG    res;
	TCHAR   errMsg[1024];

	if ((res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Owner"),  NULL, KEY_EXECUTE , &hKey)) == 0)
	{
		if ((res = RegQueryValueEx (hKey, TEXT("Telephone"), NULL,  &dwType, (LPBYTE )strValue, &dwCount)) == 0)
		{
			if (dwType != REG_SZ)
			{
				LOG(ERROR) + "Settings/Owner Information/Telephone has invalid type";
				RegCloseKey(hKey);
				return false;
			}

			if (dwCount > 0)
			{
				strValue[dwCount + 1] = '\0';

				if (_tcslen((strValue))  == 0)
				{
					LOG(INFO) + "Settings/Owner Information/Telephone is empty";

					RegCloseKey(hKey);
					return false;
				}

				number = convertToStringA(strValue);

				RegCloseKey(hKey);
				return true;
			}
		}
	}

	RegCloseKey(hKey);
	FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, errMsg, sizeof(errMsg), NULL);
	LOG(ERROR) + errMsg;

	return false;
}

VALUE phone_number()
{
	String number;

	if (getPhoneNumFromSIMCard(number))
		return rho_ruby_create_string(number.c_str());

//	if (getPhoneNumFromSMSBearer(number))
//		return rho_ruby_create_string(number.c_str());

	if (getPhoneNumFromOwnerInfo(number))
		return rho_ruby_create_string(number.c_str());

	return rho_ruby_get_NIL();
}
#else
VALUE phone_number()
{
	return rho_ruby_get_NIL();
}
#endif

static int has_camera()
{
#ifdef OS_WINCE
/*    DEVMGR_DEVICE_INFORMATION devInfo = {0};
    GUID guidCamera = { 0xCB998A05, 0x122C, 0x4166, 0x84, 0x6A, 0x93,
                        0x3E, 0x4D, 0x7E, 0x3C, 0x86 };
    devInfo.dwSize = sizeof(devInfo);

    HANDLE hDevice = FindFirstDevice( DeviceSearchByGuid, &guidCamera, &devInfo);
    if ( hDevice != INVALID_HANDLE_VALUE )
    {
        FindClose(hDevice);
        return 1;
    }

    return 0;*/

    return 1;
#else
    return 0;
#endif
}

static double get_screen_ppi_x()
{
	HWND hWndDesktop = GetDesktopWindow();
	HDC hdcDesktop = GetDC(hWndDesktop);
	int mms = GetDeviceCaps(hdcDesktop, HORZSIZE);
	int pixels = GetDeviceCaps(hdcDesktop, HORZRES);
	double ret = (pixels*25.4)/mms;
	return ret;
}

static double get_screen_ppi_y()
{
	HWND hWndDesktop = GetDesktopWindow();
	HDC hdcDesktop = GetDC(hWndDesktop);
	int mms = GetDeviceCaps(hdcDesktop, VERTSIZE);
	int pixels = GetDeviceCaps(hdcDesktop, VERTRES);
	double ret = (pixels*25.4)/mms;
	return ret;
}

int rho_sysimpl_get_property(char* szPropName, VALUE* resValue)
{
	if (strcasecmp("has_camera",szPropName) == 0)
        {*resValue = rho_ruby_create_boolean(has_camera()); return 1;}

	if (strcasecmp("phone_number",szPropName) == 0)
        {*resValue = phone_number();return 1;}

	if (strcasecmp("ppi_x",szPropName) == 0)
        {*resValue = rho_ruby_create_double(get_screen_ppi_x()); return 1;}

	if (strcasecmp("ppi_y",szPropName) == 0)
        {*resValue = rho_ruby_create_double(get_screen_ppi_y()); return 1; }

	if (strcasecmp("device_name",szPropName) == 0)
	{
#ifdef OS_WINDOWS
		*resValue = rho_ruby_create_string("Win32");
#else
		HKEY hKey;
		if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("Ident"),
			0, KEY_READ, &hKey ) != ERROR_SUCCESS)
			return 0;

		DWORD dwType = REG_SZ;
		DWORD dwDataSize = 0;
		if ( RegQueryValueEx( hKey, _T("name"), 0, &dwType, (PBYTE)NULL,
			&dwDataSize ) != ERROR_SUCCESS)
			return 0;

		std::vector<wchar_t> deviceName(dwDataSize + 1);
		RegQueryValueEx( hKey, _T("name"), 0, &dwType, (PBYTE)&deviceName[0], &dwDataSize );
		char *s = wce_wctomb(&deviceName[0]);
		*resValue = rho_ruby_create_string(s);
		::free(s);

		RegCloseKey(hKey);
		return 1;
#endif
	}

	if (strcasecmp("os_version",szPropName) == 0)
	{
		OSVERSIONINFO osv;
		osv.dwOSVersionInfoSize = sizeof(osv);
		if (!GetVersionEx(&osv))
			return 0;
		char buf[50];
		snprintf(buf, sizeof(buf), "%u.%u.%u", (unsigned)osv.dwMajorVersion,
			(unsigned)osv.dwMinorVersion, (unsigned)osv.dwBuildNumber);
		*resValue = rho_ruby_create_string(&buf[0]);
		return 1;
	}

    return 0;
}

VALUE rho_sys_get_locale()
{
    wchar_t szLang[20];
    int nRes = GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SABBREVLANGNAME , szLang, 20);
    szLang[2] = 0;
    wcslwr(szLang);

    return rho_ruby_create_string(convertToStringA(szLang).c_str());
}

int rho_sys_get_screen_width()
{
#ifdef OS_WINCE
	return GetSystemMetrics(SM_CXSCREEN);
#else
	return CMainWindow::getScreenWidth();
#endif
}

int rho_sys_get_screen_height()
{
#ifdef OS_WINCE
	return GetSystemMetrics(SM_CYSCREEN);
#else
	return CMainWindow::getScreenHeight();
#endif
}

VALUE rho_sys_makephonecall(const char* callname, int nparams, char** param_names, char** param_values)
{
	return rho_ruby_get_NIL();
}

static int g_rho_has_network = 1;

void rho_sysimpl_sethas_network(int nValue)
{
    g_rho_has_network = nValue;
}

VALUE rho_sys_has_network()
{
	return rho_ruby_create_boolean(g_rho_has_network!=0);
}

void rho_sys_app_exit()
{
	::PostMessage(getMainWnd(), WM_COMMAND, MAKEWPARAM(IDM_EXIT,0), (LPARAM )0);
}

} //extern "C"
<|endoftext|>