Exemplo n.º 1
0
static inline INT get_element_size(const region_element* element)
{
    INT needed = sizeof(DWORD); /* DWORD for the type */
    switch(element->type)
    {
        case RegionDataRect:
            return needed + sizeof(GpRect);
        case RegionDataPath:
        {
            const GpPath *path = element->elementdata.path;
            DWORD flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
            /* 3 for headers, once again size doesn't count itself */
            needed += sizeof(DWORD) * 3;
            if (flags & FLAGS_INTPATH)
                needed += 2 * sizeof(SHORT) * path->pathdata.Count;
            else
                needed += 2 * sizeof(FLOAT) * path->pathdata.Count;

            needed += get_pathtypes_size(path);
            needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
            return needed;
        }
        case RegionDataEmptyRect:
        case RegionDataInfiniteRect:
            return needed;
        default:
            needed += get_element_size(element->elementdata.combine.left);
            needed += get_element_size(element->elementdata.combine.right);
            return needed;
    }

    return 0;
}
Exemplo n.º 2
0
EbmlElement *
kax_file_c::read_one_element() {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  int upper_lvl_el = 0;
  EbmlElement *l1  = m_es->FindNextElement(EBML_CLASS_CONTEXT(KaxSegment), upper_lvl_el, 0xFFFFFFFFL, true);

  if (!l1)
    return nullptr;

  const EbmlCallbacks *callbacks = find_ebml_callbacks(EBML_INFO(KaxSegment), EbmlId(*l1));
  if (!callbacks)
    callbacks = &EBML_CLASS_CALLBACK(KaxSegment);

  EbmlElement *l2 = nullptr;
  try {
    l1->Read(*m_es.get(), EBML_INFO_CONTEXT(*callbacks), upper_lvl_el, l2, true);

  } catch (libebml::CRTError &e) {
    mxdebug_if(m_debug_resync, boost::format("exception reading element data: %1% (%2%)\n") % e.what() % e.getError());
    m_in->setFilePointer(l1->GetElementPosition() + 1);
    delete l1;
    return nullptr;
  }

  unsigned long element_size = get_element_size(l1);
  if (m_debug_resync)
    mxinfo(boost::format("kax_file::read_one_element(): read element at %1% calculated size %2% stored size %3%\n")
           % l1->GetElementPosition() % element_size % (l1->IsFiniteSize() ? (boost::format("%1%") % l1->ElementSize()).str() : std::string("unknown")));
  m_in->setFilePointer(l1->GetElementPosition() + element_size, seek_beginning);

  return l1;
}
Exemplo n.º 3
0
/* Common code for CombineRegion*
 * All the caller has to do is get its format into an element
 */
static inline void fuse_region(GpRegion* region, region_element* left,
        region_element* right, const CombineMode mode)
{
    region->node.type = mode;
    region->node.elementdata.combine.left = left;
    region->node.elementdata.combine.right = right;

    region->header.size = sizeheader_size + get_element_size(&region->node);
    region->header.num_children += 2;
}
Exemplo n.º 4
0
/* Does not check parameters, caller must do that */
static inline GpStatus init_region(GpRegion* region, const RegionType type)
{
    region->node.type       = type;
    region->header.checksum = 0xdeadbeef;
    region->header.magic    = VERSION_MAGIC;
    region->header.num_children  = 0;
    region->header.size     = sizeheader_size + get_element_size(&region->node);

    return Ok;
}
Exemplo n.º 5
0
/*****************************************************************************
 * GdipGetRegionDataSize [GDIPLUS.@]
 */
GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
{
    TRACE("%p, %p\n", region, needed);

    if (!(region && needed))
        return InvalidParameter;

    /* header.size doesn't count header.size and header.checksum */
    *needed = sizeof(DWORD) * 2 + sizeheader_size + get_element_size(&region->node);

    return Ok;
}
Exemplo n.º 6
0
static inline INT get_element_size(const region_element* element)
{
    INT needed = sizeof(DWORD); /* DWORD for the type */
    switch(element->type)
    {
        case RegionDataRect:
            return needed + sizeof(GpRect);
        case RegionDataPath:
             needed += element->elementdata.pathdata.pathheader.size;
             needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
             return needed;
        case RegionDataEmptyRect:
        case RegionDataInfiniteRect:
            return needed;
        default:
            needed += get_element_size(element->elementdata.combine.left);
            needed += get_element_size(element->elementdata.combine.right);
            return needed;
    }

    return 0;
}
Exemplo n.º 7
0
unsigned long
kax_file_c::get_element_size(EbmlElement *e) {
  auto m = dynamic_cast<EbmlMaster *>(e);

  if (!m || e->IsFiniteSize())
    return e->GetSizeLength() + EBML_ID_LENGTH(static_cast<const EbmlId &>(*e)) + e->GetSize();

  auto max_end_pos = e->GetElementPosition() + EBML_ID_LENGTH(static_cast<const EbmlId &>(*e));
  for (int idx = 0, end = m->ListSize(); end > idx; ++idx)
    max_end_pos = std::max(max_end_pos, (*m)[idx]->GetElementPosition() + get_element_size((*m)[idx]));

  return max_end_pos - e->GetElementPosition();
}
Exemplo n.º 8
0
DWORD write_region_data(const GpRegion *region, void *data)
{
    struct region_header *header = data;
    INT filled = 0;
    DWORD size;

    size = sizeof(struct region_header) + get_element_size(&region->node);
    if (!data) return size;

    header->magic = VERSION_MAGIC2;
    header->num_children = region->num_children;
    filled += 2;
    /* With few exceptions, everything written is DWORD aligned,
     * so use that as our base */
    write_element(&region->node, (DWORD*)data, &filled);
    return size;
}
Exemplo n.º 9
0
/*****************************************************************************
 * GdipGetRegionData [GDIPLUS.@]
 *
 * Returns the header, followed by combining ops and region elements.
 *
 * PARAMS
 *  region  [I] region to retrieve from
 *  buffer  [O] buffer to hold the resulting data
 *  size    [I] size of the buffer
 *  needed  [O] (optional) how much data was written
 *
 * RETURNS
 *  SUCCESS: Ok
 *  FAILURE: InvalidParameter
 *
 * NOTES
 *  The header contains the size, a checksum, a version string, and the number
 *  of children. The size does not count itself or the checksum.
 *  Version is always something like 0xdbc01001 or 0xdbc01002
 *
 *  An element is a RECT, or PATH; Combining ops are stored as their
 *  CombineMode value. Special regions (infinite, empty) emit just their
 *  op-code; GpRectFs emit their code followed by their points; GpPaths emit
 *  their code followed by a second header for the path followed by the actual
 *  path data. Followed by the flags for each point. The pathheader contains
 *  the size of the data to follow, a version number again, followed by a count
 *  of how many points, and any special flags which may apply. 0x4000 means its
 *  a path of shorts instead of FLOAT.
 *
 *  Combining Ops are stored in reverse order from when they were constructed;
 *  the output is a tree where the left side combining area is always taken
 *  first.
 */
GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
        UINT *needed)
{
    struct _region_header
    {
        DWORD size;
        DWORD checksum;
        DWORD magic;
        DWORD num_children;
    } *region_header;
    INT filled = 0;
    UINT required;
    GpStatus status;

    TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);

    if (!region || !buffer || !size)
        return InvalidParameter;

    status = GdipGetRegionDataSize(region, &required);
    if (status != Ok) return status;
    if (size < required)
    {
        if (needed) *needed = size;
        return InsufficientBuffer;
    }

    region_header = (struct _region_header *)buffer;
    region_header->size = sizeheader_size + get_element_size(&region->node);
    region_header->checksum = 0;
    region_header->magic = VERSION_MAGIC;
    region_header->num_children = region->num_children;
    filled += 4;
    /* With few exceptions, everything written is DWORD aligned,
     * so use that as our base */
    write_element(&region->node, (DWORD*)buffer, &filled);

    if (needed)
        *needed = filled * sizeof(DWORD);

    return Ok;
}
Exemplo n.º 10
0
EbmlElement *
kax_file_c::read_next_level1_element_internal(uint32_t wanted_id) {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  m_resynced         = false;
  m_resync_start_pos = 0;

  // Read the next ID.
  int64_t search_start_pos = m_in->getFilePointer();
  vint_c actual_id         = vint_c::read_ebml_id(m_in);
  m_in->setFilePointer(search_start_pos, seek_beginning);

  if (m_debug_read_next)
    mxinfo(boost::format("kax_file::read_next_level1_element(): search at %1% for %|4$x| act id %|2$x| is_valid %3%\n") % search_start_pos % actual_id.m_value % actual_id.is_valid() % wanted_id);

  // If no valid ID was read then re-sync right away. No other tests
  // can be run.
  if (!actual_id.is_valid())
    return resync_to_level1_element(wanted_id);


  // Easiest case: next level 1 element following the previous one
  // without any element inbetween.
  if (   (wanted_id == actual_id.m_value)
      || (   (0 == wanted_id)
          && (   is_level1_element_id(actual_id)
              || is_global_element_id(actual_id)))) {
    EbmlElement *l1 = read_one_element();
    if (l1)
      return l1;
  }

  // If a specific level 1 is wanted then look for next ID by skipping
  // other level 1 or special elements. If that files fallback to a
  // byte-for-byte search for the ID.
  if ((0 != wanted_id) && (is_level1_element_id(actual_id) || is_global_element_id(actual_id))) {
    m_in->setFilePointer(search_start_pos, seek_beginning);
    EbmlElement *l1 = read_one_element();

    if (l1) {
      int64_t element_size = get_element_size(l1);
      bool ok              = (0 != element_size) && m_in->setFilePointer2(l1->GetElementPosition() + element_size, seek_beginning);

      if (m_debug_read_next)
        mxinfo(boost::format("kax_file::read_next_level1_element(): other level 1 element %1% new pos %2% fsize %3% epos %4% esize %5%\n")
               % EBML_NAME(l1)  % (l1->GetElementPosition() + element_size) % m_file_size
               % l1->GetElementPosition() % element_size);

      delete l1;

      return ok ? read_next_level1_element(wanted_id) : nullptr;
    }
  }

  // Last case: no valid ID found. Try a byte-for-byte search for the
  // next wanted/level 1 ID. Also try to locate at least three valid
  // ID/sizes, not just one ID.
  m_in->setFilePointer(search_start_pos, seek_beginning);
  return resync_to_level1_element(wanted_id);
}
Exemplo n.º 11
0
/*****************************************************************************
 * GdipCreateRegionPath [GDIPLUS.@]
 *
 * Creates a GpRegion from a GpPath
 *
 * PARAMS
 *  path    [I] path to base the region on
 *  region  [O] pointer to the newly allocated region
 *
 * RETURNS
 *  SUCCESS: Ok
 *  FAILURE: InvalidParameter
 *
 * NOTES
 *  If a path has no floating point points, its points will be stored as shorts
 *  (INTPATH)
 *
 *  If a path is empty, it is considered to be an INTPATH
 */
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
{
    region_element* element;
    GpPoint  *pointsi;
    GpPointF *pointsf;

    GpStatus stat;
    DWORD flags = FLAGS_INTPATH;
    INT count, i;

    TRACE("%p, %p\n", path, region);

    if (!(path && region))
        return InvalidParameter;

    *region = GdipAlloc(sizeof(GpRegion));
    if(!*region)
        return OutOfMemory;
    stat = init_region(*region, RegionDataPath);
    if (stat != Ok)
    {
        GdipDeleteRegion(*region);
        return stat;
    }
    element = &(*region)->node;
    count = path->pathdata.Count;

    /* Test to see if the path is an Integer path */
    if (count)
    {
        pointsi = GdipAlloc(sizeof(GpPoint) * count);
        pointsf = GdipAlloc(sizeof(GpPointF) * count);
        if (!(pointsi && pointsf))
        {
            GdipFree(pointsi);
            GdipFree(pointsf);
            GdipDeleteRegion(*region);
            return OutOfMemory;
        }

        stat = GdipGetPathPointsI(path, pointsi, count);
        if (stat != Ok)
        {
            GdipDeleteRegion(*region);
            return stat;
        }
        stat = GdipGetPathPoints(path, pointsf, count);
        if (stat != Ok)
        {
            GdipDeleteRegion(*region);
            return stat;
        }

        for (i = 0; i < count; i++)
        {
            if (!(pointsi[i].X == pointsf[i].X &&
                  pointsi[i].Y == pointsf[i].Y ))
            {
                flags = FLAGS_NOFLAGS;
                break;
            }
        }
        GdipFree(pointsi);
        GdipFree(pointsf);
    }

    stat = GdipClonePath(path, &element->elementdata.pathdata.path);
    if (stat != Ok)
    {
        GdipDeleteRegion(*region);
        return stat;
    }

    /* 3 for headers, once again size doesn't count itself */
    element->elementdata.pathdata.pathheader.size = ((sizeof(DWORD) * 3));
    switch(flags)
    {
        /* Floats, sent out as floats */
        case FLAGS_NOFLAGS:
            element->elementdata.pathdata.pathheader.size +=
                (sizeof(DWORD) * count * 2);
            break;
        /* INTs, sent out as packed shorts */
        case FLAGS_INTPATH:
            element->elementdata.pathdata.pathheader.size +=
                (sizeof(DWORD) * count);
            break;
        default:
            FIXME("Unhandled flags (%08x). Expect wrong results.\n", flags);
    }
    element->elementdata.pathdata.pathheader.size += get_pathtypes_size(path);
    element->elementdata.pathdata.pathheader.magic = VERSION_MAGIC;
    element->elementdata.pathdata.pathheader.count = count;
    element->elementdata.pathdata.pathheader.flags = flags;
    (*region)->header.size = sizeheader_size + get_element_size(element);

    return Ok;
}