diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-06-30 22:19:12 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-07-02 16:47:51 +0200 |
commit | 3764a3647224a5e9dde021828d3b17fe5fc9fdeb (patch) | |
tree | 7ed113c9743447bcd43d03bc2df388f4864ef996 /server | |
parent | 7e0099e18e98452d909d76997258ed0f44cf9a19 (diff) | |
download | spice-3764a3647224a5e9dde021828d3b17fe5fc9fdeb.tar.gz spice-3764a3647224a5e9dde021828d3b17fe5fc9fdeb.tar.xz spice-3764a3647224a5e9dde021828d3b17fe5fc9fdeb.zip |
Properly parse and marshall SpiceString
Diffstat (limited to 'server')
-rw-r--r-- | server/red_parse_qxl.c | 87 | ||||
-rw-r--r-- | server/red_worker.c | 66 |
2 files changed, 85 insertions, 68 deletions
diff --git a/server/red_parse_qxl.c b/server/red_parse_qxl.c index 3530de19..d38cad7b 100644 --- a/server/red_parse_qxl.c +++ b/server/red_parse_qxl.c @@ -375,10 +375,85 @@ static void red_put_stroke_ptr(SpiceStroke *red) free(red->path); } +static SpiceString *red_get_string(RedMemSlotInfo *slots, int group_id, + SPICE_ADDRESS addr) +{ + RedDataChunk chunks; + QXLString *qxl; + QXLRasterGlyph *start, *end; + SpiceString *red; + SpiceRasterGlyph *glyph; + uint8_t *data; + bool free_data; + size_t chunk_size, qxl_size, red_size, glyph_size; + int glyphs, bpp = 0, i; + + qxl = (QXLString *)get_virt(slots, addr, sizeof(*qxl), group_id); + chunk_size = red_get_data_chunks_ptr(slots, group_id, + get_memslot_id(slots, addr), + &chunks, &qxl->chunk); + data = red_linearize_chunk(&chunks, chunk_size, &free_data); + red_put_data_chunks(&chunks); + + qxl_size = qxl->data_size; + ASSERT(chunk_size == qxl_size); + + if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A1) { + bpp = 1; + } else if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A4) { + bpp = 4; + } else if (qxl->flags & SPICE_STRING_FLAGS_RASTER_A8) { + bpp = 8; + } + ASSERT(bpp != 0); + + start = (QXLRasterGlyph*)data; + end = (QXLRasterGlyph*)(data + chunk_size); + red_size = sizeof(SpiceString); + glyphs = 0; + while (start < end) { + ASSERT((QXLRasterGlyph*)(&start->data[0]) <= end); + glyphs++; + glyph_size = start->height * ((start->width * bpp + 7) / 8); + red_size += sizeof(SpiceRasterGlyph *) + SPICE_ALIGN(sizeof(SpiceRasterGlyph) + glyph_size, 4); + start = (QXLRasterGlyph*)(&start->data[glyph_size]); + } + ASSERT(start <= end); + ASSERT(glyphs == qxl->length); + + red = spice_malloc(red_size); + red->length = qxl->length; + red->flags = qxl->flags; + + start = (QXLRasterGlyph*)data; + end = (QXLRasterGlyph*)(data + chunk_size); + glyph = (SpiceRasterGlyph *)&red->glyphs[red->length]; + for (i = 0; i < red->length; i++) { + ASSERT((QXLRasterGlyph*)(&start->data[0]) <= end); + red->glyphs[i] = glyph; + glyph->width = start->width; + glyph->height = start->height; + red_get_point_ptr(&glyph->render_pos, &start->render_pos); + red_get_point_ptr(&glyph->glyph_origin, &start->glyph_origin); + glyph_size = glyph->height * ((glyph->width * bpp + 7) / 8); + ASSERT((QXLRasterGlyph*)(&start->data[glyph_size]) <= end); + memcpy(glyph->data, start->data, glyph_size); + start = (QXLRasterGlyph*)(&start->data[glyph_size]); + glyph = (SpiceRasterGlyph*) + (((uint8_t *)glyph) + + SPICE_ALIGN(sizeof(SpiceRasterGlyph) + glyph_size, 4)); + } + + if (free_data) { + free(data); + } + return red; +} + static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id, - SpiceText *red, QXLText *qxl) + SpiceText *red, QXLText *qxl) { - red->str = qxl->str; + red->str = red_get_string(slots, group_id, qxl->str); red_get_rect_ptr(&red->back_area, &qxl->back_area); red_get_brush_ptr(slots, group_id, &red->fore_brush, &qxl->fore_brush); red_get_brush_ptr(slots, group_id, &red->back_brush, &qxl->back_brush); @@ -386,6 +461,11 @@ static void red_get_text_ptr(RedMemSlotInfo *slots, int group_id, red->back_mode = qxl->back_mode; } +static void red_put_text_ptr(SpiceText *red) +{ + free(red->str); +} + static void red_get_whiteness_ptr(RedMemSlotInfo *slots, int group_id, SpiceWhiteness *red, QXLWhiteness *qxl) { @@ -568,6 +648,9 @@ void red_put_drawable(RedDrawable *red) case QXL_DRAW_STROKE: red_put_stroke_ptr(&red->u.stroke); break; + case QXL_DRAW_TEXT: + red_put_text_ptr(&red->u.text); + break; } } diff --git a/server/red_worker.c b/server/red_worker.c index ee81fcfb..ff0a049e 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -3948,45 +3948,6 @@ static inline void red_process_surface(RedWorker *worker, RedSurfaceCmd *surface free(surface); } -static void localize_str(RedWorker *worker, QXLPHYSICAL *in_str, uint32_t group_id) -{ - QXLString *qxl_str = (QXLString *)get_virt(&worker->mem_slots, *in_str, sizeof(QXLString), group_id); - QXLDataChunk *chunk; - SpiceString *str; - uint8_t *dest; - uint32_t data_size; - int memslot_id = get_memslot_id(&worker->mem_slots, *in_str); - - ASSERT(in_str); - str = spice_malloc_n_m(1, qxl_str->data_size, sizeof(uint32_t)); - *in_str = (QXLPHYSICAL)str; - str->length = qxl_str->length; - str->flags = qxl_str->flags; - dest = str->data; - chunk = &qxl_str->chunk; - for (;;) { - QXLPHYSICAL next_chunk; - - data_size = chunk->data_size; - validate_virt(&worker->mem_slots, (unsigned long)chunk->data, memslot_id, data_size, group_id); - memcpy(dest, chunk->data, data_size); - if (!chunk->next_chunk) { - return; - } - dest += data_size; - next_chunk = chunk->next_chunk; - memslot_id = get_memslot_id(&worker->mem_slots, next_chunk); - chunk = (QXLDataChunk *)get_virt(&worker->mem_slots, next_chunk, sizeof(QXLDataChunk), group_id); - } -} - -static void unlocalize_str(QXLPHYSICAL *str) -{ - ASSERT(str && *str); - free((void *)*str); - *str = 0; -} - static LocalImage *alloc_local_image(RedWorker *worker) { ASSERT(worker->local_images_pos < MAX_BITMAPS); @@ -4450,10 +4411,8 @@ static void red_draw_qxl_drawable(RedWorker *worker, Drawable *drawable) SpiceText text = drawable->red_drawable->u.text; localize_brush(worker, &text.fore_brush, drawable->group_id); localize_brush(worker, &text.back_brush, drawable->group_id); - localize_str(worker, &text.str, drawable->group_id); canvas->ops->draw_text(canvas, &drawable->red_drawable->bbox, &clip, &text); - unlocalize_str(&text.str); unlocalize_brush(&text.back_brush); unlocalize_brush(&text.fore_brush); break; @@ -5159,27 +5118,6 @@ static void add_buf_from_info(RedChannel *channel, SpiceMarshaller *m, AddBufInf } -static void fill_str(DisplayChannel *display_channel, SpiceMarshaller *m, - QXLPHYSICAL in_str, uint32_t group_id) -{ - RedWorker *worker; - RedChannel *channel = &display_channel->base; - int memslot_id; - SpiceString string; - - worker = channel->worker; - - ASSERT(in_str); - memslot_id = get_memslot_id(&worker->mem_slots, in_str); - QXLString *str = (QXLString *)get_virt(&worker->mem_slots, in_str, sizeof(QXLString), group_id); - string.length = str->length; - string.flags = str->flags; - spice_marshall_String(m, &string); - /* TODO: This doesn't properly marshal the glyph data */ - marshaller_add_chunk(worker, m, &str->chunk, - str->data_size, memslot_id, group_id); -} - static inline void fill_rects_clip(SpiceMarshaller *m, SpiceClipRects *data) { int i; @@ -8092,7 +8030,6 @@ static void red_send_qxl_draw_text(RedWorker *worker, SpiceText text; SpiceMarshaller *brush_pat_out; SpiceMarshaller *back_brush_pat_out; - SpiceMarshaller *str_out; fill_base(display_channel, item); @@ -8100,7 +8037,6 @@ static void red_send_qxl_draw_text(RedWorker *worker, text = drawable->u.text; spice_marshall_Text(channel->send_data.marshaller, &text, - &str_out, &brush_pat_out, &back_brush_pat_out); @@ -8110,8 +8046,6 @@ static void red_send_qxl_draw_text(RedWorker *worker, if (back_brush_pat_out) { fill_bits(display_channel, back_brush_pat_out, text.back_brush.u.pattern.pat, item, FALSE); } - - fill_str(display_channel, str_out, text.str, item->group_id); } static void red_lossy_send_qxl_draw_text(RedWorker *worker, |