/* * @implemented */ HDC WINAPI CreateICA( LPCSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszOutput, CONST DEVMODEA *lpdvmInit) { NTSTATUS Status; LPWSTR lpszDriverW, lpszDeviceW, lpszOutputW; LPDEVMODEW dvmInitW = NULL; HDC hdc = 0; Status = HEAP_strdupA2W(&lpszDriverW, lpszDriver); if (!NT_SUCCESS(Status)) SetLastError(RtlNtStatusToDosError(Status)); else { Status = HEAP_strdupA2W(&lpszDeviceW, lpszDevice); if (!NT_SUCCESS(Status)) SetLastError(RtlNtStatusToDosError(Status)); else { Status = HEAP_strdupA2W(&lpszOutputW, lpszOutput); if (!NT_SUCCESS(Status)) SetLastError(RtlNtStatusToDosError(Status)); else { if (lpdvmInit) dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit); hdc = IntCreateDICW(lpszDriverW, lpszDeviceW, lpszOutputW, lpdvmInit ? dvmInitW : NULL, 1 ); HEAP_free(dvmInitW); HEAP_free(lpszOutputW); } HEAP_free(lpszDeviceW); } HEAP_free(lpszDriverW); } return hdc; }
/* * @implemented */ HDC WINAPI ResetDCA( _In_ HDC hdc, _In_ CONST DEVMODEA *lpInitData) { LPDEVMODEW InitDataW; InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData); NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL); HEAP_free(InitDataW); return hdc; }
/** * Attempt to collapse close knots into corners, * as long as they fall below the error threshold. */ static uint curve_incremental_simplify_corners( const struct PointData *pd, struct Knot *knots, const uint knots_len, uint knots_len_remaining, const double error_sq_max, const double error_sq_2x_max, const double corner_angle, const uint dims, uint *r_corner_index_len) { #ifdef USE_TPOOL struct ElemPool_KnotCornerState epool; corner_pool_create(&epool, 0); #endif Heap *heap = HEAP_new(0); struct KnotCorner_Params params = { .pd = pd, .heap = heap, #ifdef USE_TPOOL .epool = &epool, #endif }; #ifdef USE_VLA double plane_no[dims]; double k_proj_ref[dims]; double k_proj_split[dims]; #else double *plane_no = alloca(sizeof(double) * dims); double *k_proj_ref = alloca(sizeof(double) * dims); double *k_proj_split = alloca(sizeof(double) * dims); #endif const double corner_angle_cos = cos(corner_angle); uint corner_index_len = 0; for (uint i = 0; i < knots_len; i++) { if ((knots[i].is_removed == false) && (knots[i].can_remove == true) && (knots[i].next && knots[i].next->can_remove)) { struct Knot *k_prev = &knots[i]; struct Knot *k_next = k_prev->next; /* Angle outside threshold */ if (dot_vnvn(k_prev->tan[0], k_next->tan[1], dims) < corner_angle_cos) { /* Measure distance projected onto a plane, * since the points may be offset along their own tangents. */ sub_vn_vnvn(plane_no, k_next->tan[0], k_prev->tan[1], dims); /* Compare 2x so as to allow both to be changed by maximum of error_sq_max */ const uint split_index = knot_find_split_point_on_axis( pd, k_prev, k_next, knots_len, plane_no, dims); if (split_index != SPLIT_POINT_INVALID) { const double *co_prev = ¶ms.pd->points[k_prev->index * dims]; const double *co_next = ¶ms.pd->points[k_next->index * dims]; const double *co_split = ¶ms.pd->points[split_index * dims]; project_vn_vnvn_normalized(k_proj_ref, co_prev, k_prev->tan[1], dims); project_vn_vnvn_normalized(k_proj_split, co_split, k_prev->tan[1], dims); if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) { project_vn_vnvn_normalized(k_proj_ref, co_next, k_next->tan[0], dims); project_vn_vnvn_normalized(k_proj_split, co_split, k_next->tan[0], dims); if (len_squared_vnvn(k_proj_ref, k_proj_split, dims) < error_sq_2x_max) { struct Knot *k_split = &knots[split_index]; knot_corner_error_recalculate( ¶ms, k_split, k_prev, k_next, error_sq_max, dims); } } } } } } while (HEAP_is_empty(heap) == false) { struct KnotCornerState *c = HEAP_popmin(heap); struct Knot *k_split = &knots[c->index]; /* Remove while collapsing */ struct Knot *k_prev = &knots[c->index_adjacent[0]]; struct Knot *k_next = &knots[c->index_adjacent[1]]; /* Insert */ k_split->is_removed = false; k_split->prev = k_prev; k_split->next = k_next; k_prev->next = k_split; k_next->prev = k_split; /* Update tangents */ k_split->tan[0] = k_prev->tan[1]; k_split->tan[1] = k_next->tan[0]; /* Own handles */ k_prev->handles[1] = c->handles_prev[0]; k_split->handles[0] = c->handles_prev[1]; k_split->handles[1] = c->handles_next[0]; k_next->handles[0] = c->handles_next[1]; k_prev->error_sq_next = c->error_sq[0]; k_split->error_sq_next = c->error_sq[1]; k_split->heap_node = NULL; #ifdef USE_TPOOL corner_pool_elem_free(&epool, c); #else free(c); #endif k_split->is_corner = true; knots_len_remaining++; corner_index_len++; } #ifdef USE_TPOOL corner_pool_destroy(&epool); #endif HEAP_free(heap, free); *r_corner_index_len = corner_index_len; return knots_len_remaining; }
/** * Re-adjust the curves by re-fitting points. * test the error from moving using points between the adjacent. */ static uint curve_incremental_simplify_refit( const struct PointData *pd, struct Knot *knots, const uint knots_len, uint knots_len_remaining, const double error_sq_max, const uint dims) { #ifdef USE_TPOOL struct ElemPool_KnotRefitState epool; refit_pool_create(&epool, 0); #endif Heap *heap = HEAP_new(knots_len); struct KnotRefit_Params params = { .pd = pd, .heap = heap, #ifdef USE_TPOOL .epool = &epool, #endif }; for (uint i = 0; i < knots_len; i++) { struct Knot *k = &knots[i]; if (k->can_remove && (k->is_removed == false) && (k->is_corner == false) && (k->prev && k->next)) { knot_refit_error_recalculate(¶ms, knots, knots_len, k, error_sq_max, dims); } } while (HEAP_is_empty(heap) == false) { struct Knot *k_old, *k_refit; { struct KnotRefitState *r = HEAP_popmin(heap); k_old = &knots[r->index]; k_old->heap_node = NULL; #ifdef USE_KNOT_REFIT_REMOVE if (r->index_refit == SPLIT_POINT_INVALID) { k_refit = NULL; } else #endif { k_refit = &knots[r->index_refit]; k_refit->handles[0] = r->handles_prev[1]; k_refit->handles[1] = r->handles_next[0]; } k_old->prev->handles[1] = r->handles_prev[0]; k_old->next->handles[0] = r->handles_next[1]; #ifdef USE_TPOOL refit_pool_elem_free(&epool, r); #else free(r); #endif } if (UNLIKELY(knots_len_remaining <= 2)) { continue; } struct Knot *k_prev = k_old->prev; struct Knot *k_next = k_old->next; k_old->next = NULL; k_old->prev = NULL; k_old->is_removed = true; #ifdef USE_KNOT_REFIT_REMOVE if (k_refit == NULL) { k_next->prev = k_prev; k_prev->next = k_next; knots_len_remaining -= 1; } else #endif { /* Remove ourselves */ k_next->prev = k_refit; k_prev->next = k_refit; k_refit->prev = k_prev; k_refit->next = k_next; k_refit->is_removed = false; } if (k_prev->can_remove && (k_prev->is_corner == false) && (k_prev->prev && k_prev->next)) { knot_refit_error_recalculate(¶ms, knots, knots_len, k_prev, error_sq_max, dims); } if (k_next->can_remove && (k_next->is_corner == false) && (k_next->prev && k_next->next)) { knot_refit_error_recalculate(¶ms, knots, knots_len, k_next, error_sq_max, dims); } } #ifdef USE_TPOOL refit_pool_destroy(&epool); #endif HEAP_free(heap, free); return knots_len_remaining; }
/** * Return length after being reduced. */ static uint curve_incremental_simplify( const struct PointData *pd, struct Knot *knots, const uint knots_len, uint knots_len_remaining, double error_sq_max, const uint dims) { #ifdef USE_TPOOL struct ElemPool_KnotRemoveState epool; rstate_pool_create(&epool, 0); #endif Heap *heap = HEAP_new(knots_len); struct KnotRemove_Params params = { .pd = pd, .heap = heap, #ifdef USE_TPOOL .epool = &epool, #endif }; for (uint i = 0; i < knots_len; i++) { struct Knot *k = &knots[i]; if (k->can_remove && (k->is_removed == false) && (k->is_corner == false)) { knot_remove_error_recalculate(¶ms, k, error_sq_max, dims); } } while (HEAP_is_empty(heap) == false) { struct Knot *k; { const double error_sq = HEAP_top_value(heap); struct KnotRemoveState *r = HEAP_popmin(heap); k = &knots[r->index]; k->heap_node = NULL; k->prev->handles[1] = r->handles[0]; k->next->handles[0] = r->handles[1]; k->prev->error_sq_next = error_sq; #ifdef USE_TPOOL rstate_pool_elem_free(&epool, r); #else free(r); #endif } if (UNLIKELY(knots_len_remaining <= 2)) { continue; } struct Knot *k_prev = k->prev; struct Knot *k_next = k->next; /* Remove ourselves */ k_next->prev = k_prev; k_prev->next = k_next; k->next = NULL; k->prev = NULL; k->is_removed = true; if (k_prev->can_remove && (k_prev->is_corner == false) && (k_prev->prev && k_prev->next)) { knot_remove_error_recalculate(¶ms, k_prev, error_sq_max, dims); } if (k_next->can_remove && (k_next->is_corner == false) && (k_next->prev && k_next->next)) { knot_remove_error_recalculate(¶ms, k_next, error_sq_max, dims); } knots_len_remaining -= 1; } #ifdef USE_TPOOL rstate_pool_destroy(&epool); #endif HEAP_free(heap, free); return knots_len_remaining; }
void HEAP_test() { HEAP heap; HEntry entry,*pentry; int *tmp,i; VISITCTX sorted_ctx; VASSERT( !HEAP_init( &heap, 10, sizeof(HEntry), HEntry_compare) ); tmp = shuffle(TEST_SIZE); #ifdef SHOW_RESULTS printheap(&heap); #endif for(i=0;i<TEST_SIZE;i++) { entry.Key = tmp[i]; sprintf(entry.Name,"N:%03d",tmp[i]); HEAP_push( &heap, (unsigned char *) &entry, sizeof(entry) ); #ifdef SHOW_RESULTS printheap(&heap); #endif VASSERT( HEAP_check(&heap) ); } free(tmp); #ifdef SHOW_RESULTS printf("pop!\n"); #endif VASSERT( HEAP_check(&heap) ); VASSERT( HEAP_size(&heap) == TEST_SIZE ); i = -1; while( (pentry = (HEntry *) HEAP_top( &heap )) != 0 ) { #ifdef SHOW_RESULTS printheap(&heap); printf("->%d\n",pentry->Key); #endif VASSERT(pentry->Key > i); sprintf(entry.Name,"N:%03d",pentry->Key); VASSERT( pentry->Key >= i); VASSERT( strcmp(pentry->Name,entry.Name) == 0); i = pentry->Key; HEAP_pop( &heap); } VASSERT(HEAP_check(&heap)); sorted_ctx.entry = 0; HEAP_foreach_sorted( &heap, heap_visitor_check_sorted, &sorted_ctx); HEAP_free(&heap); }
/* * @implemented */ HDC WINAPI CreateDCA ( LPCSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszOutput, CONST DEVMODEA * lpdvmInit) { ANSI_STRING DriverA, DeviceA, OutputA; UNICODE_STRING DriverU, DeviceU, OutputU; LPDEVMODEW dvmInitW = NULL; HDC hdc; /* * If needed, convert to Unicode * any string parameter. */ if (lpszDriver != NULL) { RtlInitAnsiString(&DriverA, (LPSTR)lpszDriver); RtlAnsiStringToUnicodeString(&DriverU, &DriverA, TRUE); } else { DriverU.Buffer = NULL; } if (lpszDevice != NULL) { RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice); RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE); } else { DeviceU.Buffer = NULL; } if (lpszOutput != NULL) { RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput); RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE); } else { OutputU.Buffer = NULL; } if (lpdvmInit != NULL) dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit); hdc = IntCreateDICW(DriverU.Buffer, DeviceU.Buffer, OutputU.Buffer, lpdvmInit ? dvmInitW : NULL, 0); HEAP_free(dvmInitW); /* Free Unicode parameters. */ RtlFreeUnicodeString(&DriverU); RtlFreeUnicodeString(&DeviceU); RtlFreeUnicodeString(&OutputU); /* Return the DC handle. */ return hdc; }