diff options
author | Andrzej Hunt <andrzej.hunt@collabora.com> | 2014-07-08 08:54:13 +0200 |
---|---|---|
committer | Andrzej Hunt <andrzej.hunt@collabora.com> | 2014-07-12 05:19:12 +0200 |
commit | a864ab2ef17e02930df5ae91112b5104bdea1e39 (patch) | |
tree | ecd53e8aa034a7eb02197795be6bf9923a7206f4 /libreofficekit/qa | |
parent | dfdc9f5ba4493369a0c6fb3a1d7c5781deeb5bc2 (diff) |
Implement a (qa-only) quad-tiled viewer.
I.e. we subdivide the document into 4 tiles: one at 100% scaling,
one at 200%, one at 50%, one at 25% -- these are then post-scaled
in gdk) and assembled to show as one document again.
This is specifically a test only widget, primarily to be able to quickly
spot any tile positioning/border-transition issues.
We could theoretically make this widget inherit from the original widget,
however that would mean having to introduce virtual methods etc., which
is not something that we'd want in production -- in the longer run
that widget will hopefully be extended to have proper tile composition etc.,
which would then break this widget too if it were inheriting from there.
Change-Id: Ib880a1614f89724135e753013cf91aec25973e39
Diffstat (limited to 'libreofficekit/qa')
-rw-r--r-- | libreofficekit/qa/lokdocview_quad/lokdocview_quad.c | 253 | ||||
-rw-r--r-- | libreofficekit/qa/lokdocview_quad/lokdocview_quad.h | 66 |
2 files changed, 319 insertions, 0 deletions
diff --git a/libreofficekit/qa/lokdocview_quad/lokdocview_quad.c b/libreofficekit/qa/lokdocview_quad/lokdocview_quad.c new file mode 100644 index 000000000000..cbff8856a70e --- /dev/null +++ b/libreofficekit/qa/lokdocview_quad/lokdocview_quad.c @@ -0,0 +1,253 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/types.h> + +#define LOK_USE_UNSTABLE_API +#include <LibreOfficeKit/LibreOfficeKit.h> + +#include "lokdocview_quad.h" + +static void lok_docview_quad_class_init( LOKDocViewQuadClass* pClass ); +static void lok_docview_quad_init( LOKDocViewQuad* pDocView ); + +// We specifically need to destroy the document when closing in order to ensure +// that lock files etc. are cleaned up. +void lcl_onDestroy( LOKDocViewQuad* pDocView, gpointer pData ) +{ + (void) pData; + if ( pDocView->pDocument ) + pDocView->pDocument->pClass->destroy( pDocView->pDocument ); + pDocView->pDocument = NULL; +} + +SAL_DLLPUBLIC_EXPORT guint lok_docview_quad_get_type() +{ + static guint lok_docview_quad_type = 0; + + if (!lok_docview_quad_type) + { + GtkTypeInfo lok_docview_quad_info = + { + "LokDocViewQuad", + sizeof( LOKDocViewQuad ), + sizeof( LOKDocViewQuadClass ), + (GtkClassInitFunc) lok_docview_quad_class_init, + (GtkObjectInitFunc) lok_docview_quad_init, + NULL, + NULL, + (GtkClassInitFunc) NULL + }; + + lok_docview_quad_type = gtk_type_unique( gtk_scrolled_window_get_type(), &lok_docview_quad_info ); + } + return lok_docview_quad_type; +} + +static void lok_docview_quad_class_init( LOKDocViewQuadClass* pClass ) +{ + pClass->lok_docview_quad = NULL; +} + +static void lok_docview_quad_init( LOKDocViewQuad* pDocView ) +{ + int x, y; + + // Gtk ScrolledWindow is apparently not fully initialised yet, we specifically + // have to set the [hv]adjustment to prevent GTK assertions from firing, see + // https://bugzilla.gnome.org/show_bug.cgi?id=438114 for more info. + gtk_scrolled_window_set_hadjustment( GTK_SCROLLED_WINDOW( pDocView ), NULL ); + gtk_scrolled_window_set_vadjustment( GTK_SCROLLED_WINDOW( pDocView ), NULL ); + + pDocView->pEventBox = gtk_event_box_new(); + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(pDocView), + pDocView->pEventBox ); + + pDocView->pGrid = gtk_table_new( 2, 2, TRUE ); + gtk_container_add( GTK_CONTAINER( pDocView->pEventBox ), pDocView->pGrid ); + + for ( x = 0; x < 2; x++ ) + { + for ( y = 0; y < 2; y++ ) + { + pDocView->pCanvas[x][y] = gtk_image_new(); + gtk_table_attach_defaults( GTK_TABLE( pDocView->pGrid ), pDocView->pCanvas[x][y], x, x+1, y, y+1 ); + //gtk_container_add( GTK_CONTAINER( pDocView->pEventBox ), pDocView->pCanvas ); + gtk_widget_show( pDocView->pCanvas[x][y] ); + + pDocView->pPixBuf[x][y] = 0; + } + } + + gtk_widget_show( pDocView->pGrid ); + gtk_widget_show( pDocView->pEventBox ); + + // TODO: figure out a clever view of getting paths set up. + pDocView->pOffice = 0; + pDocView->pDocument = 0; + + pDocView->fZoom = 1; + + gtk_signal_connect( GTK_OBJECT(pDocView), "destroy", + GTK_SIGNAL_FUNC(lcl_onDestroy), NULL ); +} + +SAL_DLLPUBLIC_EXPORT GtkWidget* lok_docview_quad_new( LibreOfficeKit* pOffice ) +{ + LOKDocViewQuad* pDocView = gtk_type_new( lok_docview_quad_get_type() ); + pDocView->pOffice = pOffice; + return GTK_WIDGET( pDocView ); +} + +void renderDocument( LOKDocViewQuad* pDocView ) +{ + long nWidth, nHeight; + int nRenderWidth, nRenderHeight; + int nRowStride; + int x, y; + GdkPixbuf* pTempBuf; + + g_assert( pDocView->pDocument ); + + for ( x = 0; x < 2; x++ ) + { + for ( y = 0; y < 2; y++ ) + { + if ( pDocView->pPixBuf[x][y] ) + { + g_object_unref( G_OBJECT( pDocView->pPixBuf[x][y] ) ); + } + } + } + + pDocView->pDocument->pClass->getDocumentSize( pDocView->pDocument, &nWidth, &nHeight ); + + // Draw the whole document at once (for now) + + // TODO: we really should scale by screen DPI here -- 10 seems to be a vaguely + // correct factor for my screen at least. + nRenderWidth = nWidth * pDocView->fZoom / 10; + nRenderHeight = nHeight * pDocView->fZoom / 10; + + // TOP-LEFT: standard + // TOP-RIGHT: 2x resolution rendered (post-scaled to 50%) + // BOTTOM-LEFT: 1/2 resolution rendered (post-scaled 200%) + // BOTTOM-RIGHT: 1/2 resolution rendered (post-scaled 400%) + pDocView->pPixBuf[0][0] = gdk_pixbuf_new( GDK_COLORSPACE_RGB, + TRUE, 8, + nRenderWidth / 2, nRenderHeight / 2 ); + pDocView->pDocument->pClass->paintTile( pDocView->pDocument, + gdk_pixbuf_get_pixels( pDocView->pPixBuf[0][0] ), + nRenderWidth / 2, nRenderHeight / 2, + &nRowStride, + 0, 0, // origin + nWidth / 2, nHeight / 2 ); + + pDocView->pPixBuf[1][0] = gdk_pixbuf_new( GDK_COLORSPACE_RGB, + TRUE, 8, + nRenderWidth, nRenderHeight ); + pDocView->pDocument->pClass->paintTile( pDocView->pDocument, + gdk_pixbuf_get_pixels( pDocView->pPixBuf[1][0] ), + nRenderWidth, nRenderHeight, + &nRowStride, + nWidth / 2, 0, + nWidth / 2, nHeight / 2 ); + pTempBuf = gdk_pixbuf_scale_simple( GDK_PIXBUF( pDocView->pPixBuf[1][0] ), + nRenderWidth / 2, + nRenderHeight / 2, + GDK_INTERP_BILINEAR ); + g_object_unref( G_OBJECT( pDocView->pPixBuf[1][0] ) ); + pDocView->pPixBuf[1][0] = pTempBuf; + + + pDocView->pPixBuf[0][1] = gdk_pixbuf_new( GDK_COLORSPACE_RGB, + TRUE, 8, + nRenderWidth / 4, nRenderHeight / 4 ); + pDocView->pDocument->pClass->paintTile( pDocView->pDocument, + gdk_pixbuf_get_pixels( pDocView->pPixBuf[0][1] ), + nRenderWidth / 4, nRenderHeight / 4, + &nRowStride, + 0, nHeight / 2, + nWidth / 2, nHeight / 2 ); + pTempBuf = gdk_pixbuf_scale_simple( GDK_PIXBUF( pDocView->pPixBuf[0][1] ), + nRenderWidth / 2, + nRenderHeight / 2, + GDK_INTERP_BILINEAR ); + g_object_unref( G_OBJECT( pDocView->pPixBuf[0][1] ) ); + pDocView->pPixBuf[0][1] = pTempBuf; + + pDocView->pPixBuf[1][1] = gdk_pixbuf_new( GDK_COLORSPACE_RGB, + TRUE, 8, + nRenderWidth / 8, nRenderHeight / 8 ); + pDocView->pDocument->pClass->paintTile( pDocView->pDocument, + gdk_pixbuf_get_pixels( pDocView->pPixBuf[1][1] ), + nRenderWidth / 8, nRenderHeight / 8, + &nRowStride, + nWidth / 2, nHeight / 2, + nWidth / 2, nHeight / 2 ); + pTempBuf = gdk_pixbuf_scale_simple( GDK_PIXBUF( pDocView->pPixBuf[1][1] ), + nRenderWidth / 2, + nRenderHeight / 2, + GDK_INTERP_BILINEAR ); + g_object_unref( G_OBJECT( pDocView->pPixBuf[1][1] ) ); + pDocView->pPixBuf[1][1] = pTempBuf; + + + + // TODO: double check that the rowstride really matches what we expected, + // although presumably we'd already be crashing by now if things were + // wrong. + (void) nRowStride; + + // gtk_image_set_from_pixbuf( GTK_IMAGE( pDocView->pCanvas ), pDocView->pPixBuf ); + for ( x = 0; x < 2; x++ ) + { + for ( y = 0; y < 2; y++ ) + { + gtk_image_set_from_pixbuf( GTK_IMAGE( pDocView->pCanvas[x][y] ), pDocView->pPixBuf[x][y] ); + } + } +} + +SAL_DLLPUBLIC_EXPORT gboolean lok_docview_quad_open_document( LOKDocViewQuad* pDocView, char* pPath ) +{ + if ( pDocView->pDocument ) + { + pDocView->pDocument->pClass->destroy( pDocView->pDocument ); + pDocView->pDocument = NULL; + } + + pDocView->pDocument = pDocView->pOffice->pClass->documentLoad( pDocView->pOffice, + pPath ); + if ( !pDocView->pDocument ) + { + // FIXME: should have a GError parameter and populate it. + char *pError = pDocView->pOffice->pClass->getError( pDocView->pOffice ); + fprintf( stderr, "Error opening document '%s'\n", pError ); + return FALSE; + } + else + renderDocument( pDocView ); + + return TRUE; +} + +SAL_DLLPUBLIC_EXPORT void lok_docview_quad_set_zoom ( LOKDocViewQuad* pDocView, float fZoom ) +{ + pDocView->fZoom = fZoom; + renderDocument( pDocView ); + // TODO: maybe remember and reset positiong? +} + +SAL_DLLPUBLIC_EXPORT float lok_docview_quad_get_zoom ( LOKDocViewQuad* pDocView ) +{ + return pDocView->fZoom; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/libreofficekit/qa/lokdocview_quad/lokdocview_quad.h b/libreofficekit/qa/lokdocview_quad/lokdocview_quad.h new file mode 100644 index 000000000000..3124e5f6fd2f --- /dev/null +++ b/libreofficekit/qa/lokdocview_quad/lokdocview_quad.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_LOK_QA_INC_LIBREOFFICEKITGTK_H +#define INCLUDED_LOK_QA_INC_LIBREOFFICEKITGTK_H + +#include <gtk/gtk.h> +#include <gdk/gdk.h> + +#define LOK_USE_UNSTABLE_API +#include <LibreOfficeKit/LibreOfficeKit.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define LOK_DOCVIEW_QUAD(obj) GTK_CHECK_CAST (obj, lok_docview_quad_get_type(), LOKDocViewQuad) +#define LOK_DOCVIEW_QUAD_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, lok_docview_quad_get_type(), LOKDocViewQuadClass) +#define IS_LOK_DOCVIEW_QUAD(obj) GTK_CHECK_TYPE (obj, lok_docview_quad_get_type()) + + +typedef struct _LOKDocViewQuad LOKDocViewQuad; +typedef struct _LOKDocViewQuadClass LOKDocViewQuadClass; + +struct _LOKDocViewQuad +{ + GtkScrolledWindow scrollWindow; + + GtkWidget* pEventBox; + GtkWidget* pGrid; + GtkWidget* pCanvas[2][2]; + GdkPixbuf* pPixBuf[2][2]; + + float fZoom; + + LibreOfficeKit* pOffice; + LibreOfficeKitDocument* pDocument; +}; + +struct _LOKDocViewQuadClass +{ + GtkScrolledWindowClass parent_class; + + void (*lok_docview_quad) (LOKDocViewQuad* pDocView); +}; + +guint lok_docview_quad_get_type (void); +GtkWidget* lok_docview_quad_new ( LibreOfficeKit* pOffice ); +gboolean lok_docview_quad_open_document (LOKDocViewQuad* pDocView, + char* pPath); +void lok_docview_quad_set_zoom (LOKDocViewQuad* pDocView, + float fZoom); +float lok_docview_quad_get_zoom (LOKDocViewQuad* pDocView); + +#ifdef __cplusplus +} +#endif + +#endif |