static void dashed_pen_line_callback(dibdrv_physdev *pdev, INT x, INT y) { RECT rect; DWORD and, xor; get_dash_colors(pdev, &and, &xor); skip_dash(pdev, 1); rect.left = x; rect.right = x + 1; rect.top = y; rect.bottom = y + 1; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); return; }
ngx_int_t ngx_http_vod_parse_uri_file_name( ngx_http_request_t* r, u_char* start_pos, u_char* end_pos, uint32_t flags, request_params_t* result) { uint32_t default_tracks_mask; uint32_t* tracks_mask; uint32_t* end_mask; uint32_t* cur_mask; uint32_t masks_per_sequence; uint32_t sequence_index; uint32_t clip_index; uint32_t media_type; language_id_t lang_id; default_tracks_mask = (flags & PARSE_FILE_NAME_MULTI_STREAMS_PER_TYPE) ? 0xffffffff : 1; for (media_type = 0; media_type < MEDIA_TYPE_COUNT; media_type++) { result->tracks_mask[media_type] = default_tracks_mask; } result->sequences_mask = 0xffffffff; result->clip_index = INVALID_CLIP_INDEX; // segment index if ((flags & PARSE_FILE_NAME_EXPECT_SEGMENT_INDEX) != 0) { if (start_pos < end_pos && *start_pos == '-') { start_pos++; // skip the - } start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &result->segment_index); if (result->segment_index <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse segment index"); return NGX_HTTP_BAD_REQUEST; } result->segment_index--; // convert to 0-based } skip_dash(start_pos, end_pos); // clip index if (*start_pos == 'c') { start_pos++; // skip the c start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &clip_index); if (clip_index <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse clip index"); return NGX_HTTP_BAD_REQUEST; } result->clip_index = clip_index - 1; skip_dash(start_pos, end_pos); } // sequence id if (*start_pos == 's') { start_pos++; // skip the s result->sequence_id.data = start_pos; while (start_pos < end_pos && *start_pos != '-') { start_pos++; } result->sequence_id.len = start_pos - result->sequence_id.data; skip_dash(start_pos, end_pos); } // sequence (file) index if (*start_pos == 'f') { tracks_mask = result->tracks_mask; masks_per_sequence = 0; result->sequences_mask = 0; for (;;) { start_pos++; // skip the f if (start_pos >= end_pos || *start_pos < '1' || *start_pos > '9') { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: missing index following sequence selector"); return NGX_HTTP_BAD_REQUEST; } sequence_index = *start_pos - '0'; start_pos++; // skip the digit if (start_pos < end_pos && *start_pos >= '0' && *start_pos <= '9') { sequence_index = sequence_index * 10 + *start_pos - '0'; if (sequence_index > MAX_SEQUENCES) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: sequence index too big"); return NGX_HTTP_BAD_REQUEST; } start_pos++; // skip the digit } sequence_index--; // Note: sequence_index cannot be 0 here result->sequences_mask |= (1 << sequence_index); skip_dash(start_pos, end_pos); if (*start_pos == 'v' || *start_pos == 'a') { start_pos = ngx_http_vod_extract_track_tokens( start_pos, end_pos, tracks_mask + masks_per_sequence * sequence_index); if (start_pos == NULL) { return NGX_OK; } } if (*start_pos != 'f') { break; } if (result->sequence_tracks_mask != NULL) { continue; } // more than one sequence, allocate the per sequence tracks mask result->sequence_tracks_mask = ngx_palloc(r->pool, sizeof(result->sequence_tracks_mask[0]) * MEDIA_TYPE_COUNT * MAX_SEQUENCES); if (result->sequence_tracks_mask == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: ngx_palloc failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } // initialize the mask with the default cur_mask = result->sequence_tracks_mask; end_mask = cur_mask + MEDIA_TYPE_COUNT * MAX_SEQUENCES; for (; cur_mask < end_mask; cur_mask++) { *cur_mask = default_tracks_mask; } // copy the currently parsed mask to its place tracks_mask = result->sequence_tracks_mask + sequence_index * MEDIA_TYPE_COUNT; ngx_memcpy(tracks_mask, result->tracks_mask, sizeof(tracks_mask[0]) * MEDIA_TYPE_COUNT); // restore the global mask to the default for (media_type = 0; media_type < MEDIA_TYPE_COUNT; media_type++) { result->tracks_mask[media_type] = default_tracks_mask; } // from now on, parse directly to the sequence tracks mask tracks_mask = result->sequence_tracks_mask; masks_per_sequence = MEDIA_TYPE_COUNT; } } else if (*start_pos == 'v' || *start_pos == 'a') { // tracks start_pos = ngx_http_vod_extract_track_tokens(start_pos, end_pos, result->tracks_mask); if (start_pos == NULL) { return NGX_OK; } } // languages if (*start_pos == 'l') { result->langs_mask = ngx_pnalloc(r->pool, LANG_MASK_SIZE); if (result->langs_mask == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: ngx_pnalloc failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_memzero(result->langs_mask, LANG_MASK_SIZE); for (;;) { start_pos++; // skip the l if (start_pos + LANG_ISO639_2_LEN > end_pos) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: language specifier length must be 3 characters"); return NGX_HTTP_BAD_REQUEST; } lang_id = lang_parse_iso639_2_code(iso639_2_str_to_int(start_pos)); if (lang_id == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse language specifier %*s", (size_t)3, start_pos); return NGX_HTTP_BAD_REQUEST; } vod_set_bit(result->langs_mask, lang_id); start_pos += LANG_ISO639_2_LEN; skip_dash(start_pos, end_pos); if (*start_pos != 'l') { break; } } } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: did not consume the whole name"); return NGX_HTTP_BAD_REQUEST; }
static BOOL dashed_pen_line(dibdrv_physdev *pdev, POINT *start, POINT *end) { const WINEREGION *clip = get_wine_region(pdev->clip); DWORD and, xor; int i, dash_len; RECT rect; const dash_pos start_pos = pdev->dash_pos; if(start->y == end->y) /* hline */ { BOOL l_to_r; INT left, right, cur_x; rect.top = start->y; rect.bottom = start->y + 1; if(start->x <= end->x) { left = start->x; right = end->x - 1; l_to_r = TRUE; } else { left = end->x + 1; right = start->x; l_to_r = FALSE; } for(i = 0; i < clip->numRects; i++) { if(clip->rects[i].top > start->y) break; if(clip->rects[i].bottom <= start->y) continue; if(clip->rects[i].right > left && clip->rects[i].left <= right) { int clipped_left = max(clip->rects[i].left, left); int clipped_right = min(clip->rects[i].right - 1, right); pdev->dash_pos = start_pos; if(l_to_r) { cur_x = clipped_left; if(cur_x != left) skip_dash(pdev, clipped_left - left); while(cur_x <= clipped_right) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_x + dash_len > clipped_right + 1) dash_len = clipped_right - cur_x + 1; rect.left = cur_x; rect.right = cur_x + dash_len; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_x += dash_len; skip_dash(pdev, dash_len); } } else { cur_x = clipped_right; if(cur_x != right) skip_dash(pdev, right - clipped_right); while(cur_x >= clipped_left) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_x - dash_len < clipped_left - 1) dash_len = cur_x - clipped_left + 1; rect.left = cur_x - dash_len + 1; rect.right = cur_x + 1; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_x -= dash_len; skip_dash(pdev, dash_len); } } } } pdev->dash_pos = start_pos; skip_dash(pdev, right - left + 1); } else if(start->x == end->x) /* vline */ { BOOL t_to_b; INT top, bottom, cur_y; rect.left = start->x; rect.right = start->x + 1; if(start->y <= end->y) { top = start->y; bottom = end->y - 1; t_to_b = TRUE; } else { top = end->y + 1; bottom = start->y; t_to_b = FALSE; } for(i = 0; i < clip->numRects; i++) { if(clip->rects[i].top > bottom) break; if(clip->rects[i].bottom <= top) continue; if(clip->rects[i].right > start->x && clip->rects[i].left <= start->x) { int clipped_top = max(clip->rects[i].top, top); int clipped_bottom = min(clip->rects[i].bottom - 1, bottom); pdev->dash_pos = start_pos; if(t_to_b) { cur_y = clipped_top; if(cur_y != top) skip_dash(pdev, clipped_top - top); while(cur_y <= clipped_bottom) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_y + dash_len > clipped_bottom + 1) dash_len = clipped_bottom - cur_y + 1; rect.top = cur_y; rect.bottom = cur_y + dash_len; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_y += dash_len; skip_dash(pdev, dash_len); } } else { cur_y = clipped_bottom; if(cur_y != bottom) skip_dash(pdev, bottom - clipped_bottom); while(cur_y >= clipped_top) { get_dash_colors(pdev, &and, &xor); dash_len = pdev->dash_pos.left_in_dash; if(cur_y - dash_len < clipped_top - 1) dash_len = cur_y - clipped_top + 1; rect.top = cur_y - dash_len + 1; rect.bottom = cur_y + 1; pdev->dib.funcs->solid_rects(&pdev->dib, 1, &rect, and, xor); cur_y -= dash_len; skip_dash(pdev, dash_len); } } } } pdev->dash_pos = start_pos; skip_dash(pdev, bottom - top + 1); } else { bres_params params; INT dx = end->x - start->x; INT dy = end->y - start->y; INT i; params.dx = abs(dx); params.dy = abs(dy); params.octant = get_octant_mask(dx, dy); /* Octants 3, 5, 6 and 8 take a bias */ params.bias = (params.octant & 0xb4) ? 1 : 0; for(i = 0; i < clip->numRects; i++) { POINT clipped_start, clipped_end; int clip_status; clip_status = clip_line(start, end, clip->rects + i, ¶ms, &clipped_start, &clipped_end); if(clip_status) { int m = abs(clipped_start.x - start->x); int n = abs(clipped_start.y - start->y); int err; BOOL last_pt = FALSE; pdev->dash_pos = start_pos; if(is_xmajor(params.octant)) { err = 2 * params.dy - params.dx + m * 2 * params.dy - n * 2 * params.dx; skip_dash(pdev, m); } else { err = 2 * params.dx - params.dy + n * 2 * params.dx - m * 2 * params.dy; skip_dash(pdev, n); } if(clip_status == 1 && (end->x != clipped_end.x || end->y != clipped_end.y)) last_pt = TRUE; bres_line_with_bias(clipped_start.x, clipped_start.y, clipped_end.x, clipped_end.y, ¶ms, err, last_pt, dashed_pen_line_callback, pdev); if(clip_status == 2) break; /* completely unclipped, so we can finish */ } } pdev->dash_pos = start_pos; if(is_xmajor(params.octant)) skip_dash(pdev, params.dx); else skip_dash(pdev, params.dy); } release_wine_region(pdev->clip); return TRUE; }
ngx_int_t ngx_http_vod_parse_uri_file_name( ngx_http_request_t* r, u_char* start_pos, u_char* end_pos, uint32_t flags, request_params_t* result) { sequence_tracks_mask_t* sequence_tracks_mask_end; sequence_tracks_mask_t* sequence_tracks_mask; ngx_str_t* cur_sequence_id; ngx_str_t* last_sequence_id; uint32_t default_tracks_mask; uint32_t* tracks_mask; uint32_t segment_index_shift; uint32_t sequence_index; uint32_t clip_index; uint32_t media_type; uint32_t pts_delay; uint32_t version; bool_t tracks_mask_updated; language_id_t lang_id; default_tracks_mask = (flags & PARSE_FILE_NAME_MULTI_STREAMS_PER_TYPE) ? 0xffffffff : 1; for (media_type = 0; media_type < MEDIA_TYPE_COUNT; media_type++) { result->tracks_mask[media_type] = default_tracks_mask; } result->sequences_mask = 0xffffffff; result->clip_index = INVALID_CLIP_INDEX; // segment index if ((flags & PARSE_FILE_NAME_EXPECT_SEGMENT_INDEX) != 0) { if (start_pos < end_pos && *start_pos == '-') { start_pos++; // skip the - } start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &result->segment_index); if (result->segment_index <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse segment index"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } result->segment_index--; // convert to 0-based skip_dash(start_pos, end_pos); // index shift if (*start_pos == 'i') { start_pos++; // skip the i start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &segment_index_shift); if (segment_index_shift <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse segment index shift"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } result->segment_index += segment_index_shift; skip_dash(start_pos, end_pos); } } else { skip_dash(start_pos, end_pos); } // clip index if (*start_pos == 'c' && (flags & PARSE_FILE_NAME_ALLOW_CLIP_INDEX) != 0) { start_pos++; // skip the c start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &clip_index); if (clip_index <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse clip index"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } result->clip_index = clip_index - 1; skip_dash(start_pos, end_pos); } // sequence (file) index if (*start_pos == 'f' || *start_pos == 's') { result->sequences_mask = 0; cur_sequence_id = result->sequence_ids; last_sequence_id = cur_sequence_id + MAX_SEQUENCE_IDS; sequence_tracks_mask = NULL; sequence_tracks_mask_end = NULL; tracks_mask_updated = FALSE; for (;;) { if (*start_pos == 'f') { // sequence index start_pos++; // skip the f if (start_pos >= end_pos || *start_pos < '1' || *start_pos > '9') { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: missing index following sequence selector"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } sequence_index = *start_pos - '0'; start_pos++; // skip the digit if (start_pos < end_pos && *start_pos >= '0' && *start_pos <= '9') { sequence_index = sequence_index * 10 + *start_pos - '0'; if (sequence_index > MAX_SEQUENCES) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: sequence index too big"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } start_pos++; // skip the digit } sequence_index--; // Note: sequence_index cannot be 0 here result->sequences_mask |= (1 << sequence_index); } else { // sequence id start_pos++; // skip the s if (cur_sequence_id >= last_sequence_id) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: the number of sequence ids exceeds the limit"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } cur_sequence_id->data = start_pos; while (start_pos < end_pos && *start_pos != '-') { start_pos++; } cur_sequence_id->len = start_pos - cur_sequence_id->data; cur_sequence_id++; sequence_index = -(cur_sequence_id - result->sequence_ids); } skip_dash(start_pos, end_pos); // tracks spec if (*start_pos == 'v' || *start_pos == 'a') { if (sequence_tracks_mask != NULL) { if (sequence_tracks_mask >= sequence_tracks_mask_end) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: the number of track specs exceeds the limit"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } sequence_tracks_mask->index = sequence_index; tracks_mask = sequence_tracks_mask->tracks_mask; sequence_tracks_mask++; result->sequence_tracks_mask_end = sequence_tracks_mask; } else { tracks_mask_updated = TRUE; tracks_mask = result->tracks_mask; } start_pos = ngx_http_vod_extract_track_tokens( start_pos, end_pos, tracks_mask); if (start_pos == NULL) { return NGX_OK; } } if (*start_pos != 'f' && *start_pos != 's') { break; } if (sequence_tracks_mask != NULL) { continue; } // more than one sequence, allocate the per sequence tracks mask sequence_tracks_mask = ngx_palloc(r->pool, sizeof(sequence_tracks_mask[0]) * MAX_SEQUENCE_TRACKS_MASKS); if (sequence_tracks_mask == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: ngx_palloc failed"); return ngx_http_vod_status_to_ngx_error(r, VOD_ALLOC_FAILED); } sequence_tracks_mask_end = sequence_tracks_mask + MAX_SEQUENCE_TRACKS_MASKS; result->sequence_tracks_mask = sequence_tracks_mask; result->sequence_tracks_mask_end = sequence_tracks_mask; if (tracks_mask_updated) { // add the currently parsed mask to the array sequence_tracks_mask->index = sequence_index; ngx_memcpy(sequence_tracks_mask->tracks_mask, result->tracks_mask, sizeof(sequence_tracks_mask->tracks_mask)); sequence_tracks_mask++; result->sequence_tracks_mask_end = sequence_tracks_mask; // restore the global mask to the default for (media_type = 0; media_type < MEDIA_TYPE_COUNT; media_type++) { result->tracks_mask[media_type] = default_tracks_mask; } } } } else if (*start_pos == 'v' || *start_pos == 'a') { // tracks start_pos = ngx_http_vod_extract_track_tokens(start_pos, end_pos, result->tracks_mask); if (start_pos == NULL) { return NGX_OK; } } // pts delay if (*start_pos == 'p') { start_pos++; // skip the p start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &pts_delay); if (pts_delay <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse pts delay"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } result->pts_delay = pts_delay; skip_dash(start_pos, end_pos); } // languages if (*start_pos == 'l') { result->langs_mask = ngx_pnalloc(r->pool, LANG_MASK_SIZE); if (result->langs_mask == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: ngx_pnalloc failed"); return ngx_http_vod_status_to_ngx_error(r, VOD_ALLOC_FAILED); } ngx_memzero(result->langs_mask, LANG_MASK_SIZE); for (;;) { start_pos++; // skip the l if (start_pos + LANG_ISO639_3_LEN > end_pos) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: language specifier length must be 3 characters"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } lang_id = lang_parse_iso639_3_code(iso639_3_str_to_int(start_pos)); if (lang_id == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse language specifier %*s", (size_t)3, start_pos); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } vod_set_bit(result->langs_mask, lang_id); start_pos += LANG_ISO639_3_LEN; skip_dash(start_pos, end_pos); if (*start_pos != 'l') { break; } } } // version if (*start_pos == 'x') { start_pos++; // skip the x start_pos = parse_utils_extract_uint32_token(start_pos, end_pos, &version); if (version <= 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: failed to parse version"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); } result->version = version - 1; skip_dash(start_pos, end_pos); } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_vod_parse_uri_file_name: did not consume the whole name"); return ngx_http_vod_status_to_ngx_error(r, VOD_BAD_REQUEST); }